Flutter 学习分享
一. Flutter介绍:
1.初识Flutter:
- Flutter是 Google 推出的免费开源跨平台开发框架,可以快速在多个平台上搭建界面;
- Flutter帮助开发者使用一套代码开发高性能、高稳定性、高帧率、低延迟的Android和iOS应用;
- Flutter提供了两种主题的设计风格,Material Design和 Cupertino Design (偏iOS);
- Flutter使用的是 Dart 语言,是面向对象的语言,支持null-safe;
2.Flutter项目结构:
文件及文件夹说明:
- android:android平台相关文件,提交审核时需要修改里面的配置;
- ios:ios平台相关文件,提交审核时需要修改里面的配置;
- linux:linux平台相关文件;
- windows:windows平台相关文件;
- macos:macos平台相关文件;
- web:web平台相关文件,h5文件输出,可用于部署服务器;
- assets:静态文件夹,如图片,json文件;
- lib:项目代码主要目录,在此开发APP主要功能;
- pubspec.yaml:项目配置文件,记录着工程中的版本号、第三方库及静态资源路径等;
二. StatefulWidget及生命周期:
1.StatefulWidget:
说明:
- 在整个生命周期中,此widget里面内容可变;
- 自定义Widget选择性继承StatefulWidget;
- 常见的StatefulWidget:CheckBox、TabBar、TextFeild等;
2.StatelessWidget:
说明:
- 在整个生命周期中,此widget里面内容不可变;
- 自定义Widget选择性继承StatelessWidget;
- 常见的StatelessWidget:Container、ScrollView、Text、Divider等;
3.Flutter LifeCycle:
说明:
- Flutter生命周期大体上可以分为四个阶段:初始化、组件创建、状态变化、销毁;
- createState:该函数为 StatefulWidget 中创建 State 的方法,当 StatefulWidget 被调用时会立即执行;
- initState:该函数为 State 初始化调用,因此可以在此期间执行 State 各变量的初始赋值,同时也可以在此期间与服务端交互,获取服务端数据后调用;
- didChangeDependencies:在该组件依赖的 State 发生变化时,这里说的 State 为全局 State ,例如语言或者主题等;
- build:主要是返回需要渲染的 Widget,由于 build 会被调用多次,因此在该函数中只能做返回 Widget 相关逻辑,避免因为执行多次导致状态异常;
- reassemble:主要是提供开发阶段使用,在 debug 模式下,每次热重载都会调用该函数,因此在 debug 阶段可以在此期间增加一些 debug 代码,来检查代码问题;
- didUpdateWidget:该函数主要是在组件重新构建,比如说热重载,父组件发生 build的情况下,子组件该方法才会被调用;
- deactivate:在组件被移除节点后会被调用,如果该组件被移除节点,然后未被插入到其他节点时,则会继续调用 dispose 永久移除;
- dispose :永久移除组件,并释放组件资源;
三. Flutter 布局及交互:
Scaffold 脚手架
Scaffold(
// 脚手架
appBar: AppBar(
// 导航栏
title: const Text('页面标题'),
),
body: const Center(
child: Text('Flutter 开发'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
drawer: const Drawer()
);
Container
Container(
margin: EdgeInsets.only(left: 16),
padding: EdgeInsets.fromLTRB(6, 2, 6, 2),
decoration: new BoxDecoration(
gradient: blackLinearGradient(fromTop: true),
border: new Border.all(
color: Color(CHSColorRedView),
width: 1.0,
),
borderRadius:new BorderRadius.all(new Radius.circular(4.0)),
),
child: Text(
"广告",
style: TextStyle(color: Colors.white, fontSize: 12),
),
)
Column
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
shadowColor: Colors.red,
shape: const StadiumBorder(),
padding:EdgeInsets.symmetric(horizontal: 16.px, vertical: 8.px)
),
child: const Text('Swift'),
),
OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0.px),
),
side: BorderSide(width: 2.px, color: color_FF1B65B9),
),
onPressed: () {},
child: const Text('Flutter'),
),
TextButton(onPressed: () {}, child: const Text('Objective-C'))
],
)
Stack 定位
Stack(
children: [
Container(
width: 180.px,
height: 120.px,
color: Colors.green,
child: Center(
child: Text(
"Flutter知识分享",
style: TextStyle(
fontSize: 18.px,
color: Colors.white
),
),
),
),
Positioned(
right: 0,
top: 0,
child: Container(
color: Colors.red,
width: 36.px,
height: 16.px,
))
])
ListView 列表
ListView.builder(
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return HiMineListWidget(
model: HiMineModel(),
clickListener: (int indexTag) {
print(indexTag);
});
},
itemCount: 4,
)
InkWell 可被点击的Widget
InkWell(
child: Container(),
onTap: () {
Navigator.pop(context);
}
)
GestureDetector 手势
GestureDetector(
child: Container(),
onTap: () {
Navigator.pop(context);
}
)
Text
Text(
"${mModel.title}",
maxLines: 1,
overflow:TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
color: Colors.white,
)
)
FadeInImage 圆形图片
new Container(
width: 45.0,
height: 45.0,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(22.5),
child: FadeInImage.assetNetwork(
placeholder: "assets/images/ylz_blank_circular.jpg",
image: homeSonPage.item?.imgUrl ?? "",
fit: BoxFit.cover,
),
),
)
Listener 的使用
typedef void CHSHomeNavigationWidgetClickListener();
class CHSHomeNavigationWidget extends StatefulWidget {
final Key key;
final CHSHomeNavigationWidgetClickListener clickListener;
const CHSHomeNavigationWidget(this.key, this.clickListener) : super(key: key);
@override
CHSHomeNavigationWidgetState createState() => CHSHomeNavigationWidgetState();
}
class CHSHomeNavigationWidgetState extends State<CHSHomeNavigationWidget> {
@override
Widget build(BuildContext context) {
return InkWell(
onTap:() {
if (widget.clickListener != null) {
widget.clickListener();
}
}
);
}
}
Provider 的使用
import 'package:provider/provider.dart';
//在main.dart中注册Provider:
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CHSCodeProvider())
],
child: ScreenUtilInit(
designSize: Size(1125, 2436),
builder: () => buildMaterialApp(widget)
),
);
class CHSCodeProvider with ChangeNotifier, DiagnosticableTreeMixin {
String _barCodeBytes = "";
String get barCodeBytes => _barCodeBytes;
void setBarCodeBytes(String barCodeBytes) {
_barCodeBytes = barCodeBytes;
notifyListeners();
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(StringProperty('barCodeBytes', barCodeBytes));
}
}
//设置:
context.read<CHSCodeProvider>().setBarCodeBytes("${_randomBit(10)}");
//获取:
context.watch<CHSCodeProvider>().barCodeBytes
StateKey 的使用
GlobalKey<CHSHomeNavigationWithSearchWidgetState>
homeNavigationWithSearchWidgetStateKey = GlobalKey();
class CHSHomeNavigationWithSearchWidget extends StatefulWidget {
final Key key;
const CHSHomeNavigationWithSearchWidget(this.key)
: super(key: key);
@override
CHSHomeNavigationWithSearchWidgetState createState() =>
CHSHomeNavigationWithSearchWidgetState();
}
class CHSHomeNavigationWithSearchWidgetState
extends State<CHSHomeNavigationWithSearchWidget> {
void changeHomeOpacity(double homeAplhaOpacity, double aplhaOpacity) {
}
}
CHSHomeNavigationWithSearchWidget(homeNavigationWithSearchWidgetStateKey);
//调用:
homeNavigationWithSearchWidgetStateKey.currentState
?.changeHomeOpacity(0.0, 1.0);
flutter_sticky_header 之List视图 的使用
class _StickyHeaderList extends StatelessWidget {
GlobalKey<State>? stateKey = GlobalKey();
_StickyHeaderList({Key? key, this.index}) : super(key: key);
final int? index;
@override
Widget build(BuildContext context) {
return SliverStickyHeader(
sticky: false, #头部是否固定
header: Container(
),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) {
return YLZMineMemberWidget();
},
childCount: 5,
),
),
);
}
}
flutter_sticky_header 之Grid视图 的使用
class _StickyHeaderGrid extends StatelessWidget {
const _StickyHeaderGrid(
{Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return SliverStickyHeader(
sticky: false, #头部是否固定
header: buildHeaderContainer(),
sliver: SliverPadding(
padding: EdgeInsets.all(16.0),
sliver: buildSliverGrid(
context)
));
}
SliverGrid buildSliverGrid(
BuildContext context) {
double cellWidth = (MediaQuery.of(context).size.width - 32);
double desiredCellHeight = 160;
double childAspectRatio = cellWidth / desiredCellHeight;
return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
crossAxisSpacing: 16.0,
mainAxisSpacing: 16.0,
childAspectRatio: childAspectRatio),
delegate: SliverChildBuilderDelegate(
(context, index) {
return Stack();
},
childCount: 1,
),
);
}
}
Container buildHeaderContainer() {
return Container();
}
}
四. Flutter 打包:
1.iOS平台:
/Volumes/windowOSHD/AndroidStudio/flutter-sdk-3.13.5/bin/flutter --no-color build ios
2.android平台:
/Volumes/windowOSHD/AndroidStudio/flutter-sdk-3.13.5/bin/flutter --no-color build apk
五. Flutter 案例:
1.iOS平台:
[图片上传失败...(image-3ae394-1682415117744)]
2.android平台:
[图片上传失败...(image-f2268d-1682415117744)]
3.web平台:
[图片上传失败...(image-2e6351-1682415117744)]