Flutter 学习分享

Flutter 学习分享

一. Flutter介绍:

1.初识Flutter:

  • Flutter是 Google 推出的免费开源跨平台开发框架,可以快速在多个平台上搭建界面;
  • Flutter帮助开发者使用一套代码开发高性能、高稳定性、高帧率、低延迟的Android和iOS应用;
  • Flutter提供了两种主题的设计风格,Material Design和 Cupertino Design (偏iOS);
  • Flutter使用的是 Dart 语言,是面向对象的语言,支持null-safe;

2.Flutter项目结构:

Flutter 项目结构
文件及文件夹说明:
  • android:android平台相关文件,提交审核时需要修改里面的配置;
  • ios:ios平台相关文件,提交审核时需要修改里面的配置;
  • linux:linux平台相关文件;
  • windows:windows平台相关文件;
  • macos:macos平台相关文件;
  • web:web平台相关文件,h5文件输出,可用于部署服务器;
  • assets:静态文件夹,如图片,json文件;
  • lib:项目代码主要目录,在此开发APP主要功能;
  • pubspec.yaml:项目配置文件,记录着工程中的版本号、第三方库及静态资源路径等;

二. StatefulWidget及生命周期:

1.StatefulWidget:

StatefulWidget
说明:
  • 在整个生命周期中,此widget里面内容可变;
  • 自定义Widget选择性继承StatefulWidget;
  • 常见的StatefulWidget:CheckBox、TabBar、TextFeild等;

2.StatelessWidget:

StatelessWidget
说明:
  • 在整个生命周期中,此widget里面内容不可变;
  • 自定义Widget选择性继承StatelessWidget;
  • 常见的StatelessWidget:Container、ScrollView、Text、Divider等;

3.Flutter LifeCycle:

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)]

六. Flutter 学习地址:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容