Flutter开发实战 高仿微信(二)发现页

  • Flutter开发实战 高仿微信(二)发现页
    • 1.1 微信发现页面简述
    • 1.2 APP框架优化
      • 1.2.1 配置APP Logo和启动图片
      • 1.2.2 配置资源图片
      • 1.2.3 配置其他资源
        • 1.2.3.1 String 资源配置
        • 1.2.3.2 国际化
      • 1.2.4 添加依赖
      • 1.2.5 新建四个主页对应四个tabbar
    • 1.3 发现页面布局
  • 2.知识点
    • 2.1 flutter布局
      • 2.1.1 Row 水平布局
      • 2.1.2 Column 垂直布局
      • 2.1.3 Stack 层布局
      • 2.1.4 主轴
      • 2.1.5
    • 2.2 flutter基本组件
      • 2.2.1 Container
      • 2.2.2 Image
      • 2.2.3 Text
      • 2.2.4 Icon
      • 2.2.5 RaisedButton
      • 2.2.6 Scaffold
      • 2.2.7 Appbar
      • 2.2.8 FlutterLogo
      • 2.2.9 Placeholder
      • 2.2.10
  • 3.深入研究
    • 3.1 flutter项目结构分析
    • 3.2 flutter项目pubspec.yaml文件
    • 3.3 flutter项目图片资源配置

Flutter开发实战 高仿微信(二)发现页

1.1 微信发现页面简述

  1. 在上一篇《flutter开发微信之一》中讲解了项目框架的简单搭建,整个APP分为四个tabbar:微信,通讯录,发现,我。其中发现是最简单一个页面,先从最容易的页面入手,实现发现页面主页搭建。

1.2 APP框架优化

1.2.1 配置APP Logo和启动图片

  1. IOS 启动图片配置
  2. Android启动图片配置

1.2.2 配置资源图片

  1. flutter 项目资源在pubspec.yaml中配置

  2. 在代码中使用图片资源的方式:

  3. 不同分辨率的图片使用
    跟Android的多图片适配相同,将不同分辨率下的图片放到对应的目录即可,如下:

    使用代码:

new Image.asset("assets/images/a.png");
  1. flutter 在项目中加载资源的两种方式:
  • 通过rootBundle对象来加载(每个Flutter应用都有一个rootBundle对象,可以访问主asset bundle) . 如果你所在的业务场景下,拿不到context(不在widget中),那就使用这个吧,否则使用下面的方式。
import 'package:flutter/services.dart';
Widget _createBody() {return new FutureBuilder(future: rootBundle.loadString('assets/a.json'),builder: (context,snapshot){if(snapshot.hasData) {return new Text(snapshot.data.toString());}},);
  • 通过DefaultAssetBundle 来获取当前BuildContext 的 AssetBundle,推荐使用。比方法一要灵活。可以自己制定。
import 'package:flutter/services.dart';
Widget _createBody() {return new FutureBuilder(future: DefaultAssetBundle.of(context).loadString('assets/a.json'),builder: (context,snapshot){if(snapshot.hasData) {return new Text(snapshot.data.toString());}},);

1.2.3 配置其他资源

1.2.3.1 String 资源配置

新建一个.dart文件,比如uidata.dart:

import 'package:flutter/material.dart';class UIData {//routes  页面路径static const String homeRoute = "/home";static const String profileOneRoute = "/View Profile";static const String profileTwoRoute = "/Profile 2";//stringsstatic const String appName = "Flutter UIKit";//fonts  字体相关static const String quickFont = "Quicksand";static const String ralewayFont = "Raleway";static const String quickBoldFont = "Quicksand_Bold.otf";static const String quickNormalFont = "Quicksand_Book.otf";static const String quickLightFont = "Quicksand_Light.otf";//imagesstatic const String imageDir = "assets/images";static const String pkImage = "$imageDir/pk.jpg";//login  比如登录页面用到的文本static const String enter_code_label = "Phone Number";static const String enter_code_hint = "10 Digit Phone Number";//gneric 通用的文本static const String error = "Error";static const String success = "Success";static const MaterialColor ui_kit_color = Colors.grey;//colorsstatic List<Color> kitGradients = [// new Color.fromRGBO(103, 218, 255, 1.0),// new Color.fromRGBO(3, 169, 244, 1.0),// new Color.fromRGBO(0, 122, 193, 1.0),Colors.blueGrey.shade800,Colors.black87,];static List<Color> kitGradients2 = [Colors.cyan.shade600,Colors.blue.shade900];//randomcolorstatic final Random _random = new Random();/// Returns a random color.static Color next() {return new Color(0xFF000000 + _random.nextInt(0x00FFFFFF));}
}

1.2.3.2 国际化

详情参考:国际化官方教程

1.2.4 添加依赖

在pubspec.yaml 中添加依赖
注意,只有在添加平台所需相关依赖时,才需要去Android 工程中的gradle中添加依赖。

1.2.5 新建四个主页对应四个tabbar

1.3 发现页面布局

2.知识点

2.1 flutter布局

2.1.1 Row 水平布局

  1. 简介

flex水平布局控件,能够将子控件水平排列,是基于Web的flexbox的布局模式设计的。
Row子控件有灵活与不灵活的两种,Row首先列出不灵活的子控件,减去它们的总宽度,计算还有多少可用的空间。然后Row按照Flexible.flex属性确定的比例在可用空间中列出灵活的子控件。要控制灵活子控件,需要使用Expanded控件。
注意该控件不支持滑动,如果子控件超过剩余空间,会报错,如果想支持水平滑动,考虑使用ListView。
如果只有一个子控件,可以使用 Align or Center控件定义该子控件位置。

  1. 实例
 1 new Row(2   children: <Widget>[3     new Expanded(4       child: new Text('Deliver features faster', textAlign: TextAlign.center),5     ),6     new Expanded(7       child: new Text('Craft beautiful UIs', textAlign: TextAlign.center),8     ),9     new Expanded(
10       child: new FittedBox(
11         fit: BoxFit.contain, // otherwise the logo will be tiny
12         child: const FlutterLogo(),
13       ),
14     ),
15   ],
16 )
  1. 用法

2.1.2 Column 垂直布局

  1. 简介
    flex垂直布局控件,能够将子控件垂直排列。
    用法与Row控件一样。
  2. 实例
new Column(2   crossAxisAlignment: CrossAxisAlignment.start,3   mainAxisSize: MainAxisSize.min,4   children: <Widget>[5     new Text('We move under cover and we move as one'),6     new Text('Through the night, we have one shot to live another day'),7     new Text('We cannot let a stray gunshot give us away'),8     new Text('We will fight up close, seize the moment and stay in it'),9     new Text('It’s either that or meet the business end of a bayonet'),
10     new Text('The code word is ‘Rochambeau,’ dig me?'),
11     new Text('Rochambeau!', style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 2.0)),
12   ],
13 )
  1. 用法

2.1.3 Stack 层布局

  1. 简介

  2. 实例

  3. 用法

2.1.4 主轴

  1. 简介

  2. 实例

  3. 用法

2.1.5

  1. 简介

  2. 实例

  3. 用法

2.2 flutter基本组件

Flutter控件本身通常由许多小型、单用途的控件组成,结合起来产生强大的效果,例如,Container是一种常用的控件,由负责布局、绘画、定位和大小调整的几个控件组成,具体来说,Container是由LimitedBox、ConstrainedBox、 Align、Padding、DecoratedBox和Transform控件组成,而不是将Container子类化来产生自定义效果,您可以用这种新颖的方式组合这些以及其他简单的控件。

类的层次结构是扁平的,以最大化可能的组合数量。

在写应用程序时,经常会使用StatelessWidget和StatefulWidget编写新控件,两者的差别在于你是否要管理控件的状态。一个控件的主要任务是实现build函数,定义控件中其他较低层次的控件。build函数将依次构建这些控件,直到底层渲染对象。

  • Flutter控件和Android,IOS原生控件比较
Flutter控件 Android控件 IOS控件
AppBar ActionBar/ToolBar UINavgationBar
ListView ListView/RecyclerView UITableView
ListView ListView/RecyclerView UITableView
Text TextView UILabel
Center ViewGroup
Container RelativeLayout
FloatingActionButton FloatingActionButton(design库里面的)
BottomNavigationBar BottomNavigation(design库里面的)
RaisedButton/Button Button
Column LinearLayout的android:orientation=“vertical”
Row android:orientation=“horizontal”
DecorationImage ImageView
Image ImageView UIImageView
Stack FrameLayout/RelativeLayout
Algin alginParentXXX属性
resizeToAvoidBottomPadding android:windowSoftInputMode=” adjustResize属性
SingleChildScrollView ScrollView UIScrollView
CustomScrollerView Recyclerview

2.2.1 Container

  1. 简介

容器,一个常用的控件,由基本的绘制、位置和大小控件组成。负责创建矩形的可视元素,可以用BoxDecoration来设计样式,比如背景、边框和阴影,Container也有边距、填充和大小限制,另外,还可以在三维空间利用矩阵进行变换。
没有子控件的容器尽可能大,除非传入的大小约束是无限的,在这种情况下,它们尽可能小。有子控件的容器将自己的尺寸给他们的孩子。我们可以通过width、height和 constraints属性控制size。

  1. 实例
new Container(constraints: new BoxConstraints.expand(height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0,),padding: const EdgeInsets.all(8.0),color: Colors.teal.shade700,alignment: Alignment.center,child: new Text('Hello World', style: Theme.of(context).textTheme.display1.copyWith(color: Colors.white)),foregroundDecoration: new BoxDecoration(image: new DecorationImage(image: new NetworkImage('https://www.example.com/images/frame.png'),centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0),),),transform: new Matrix4.rotationZ(0.1),)
  1. 用法

2.2.2 Image

  1. 简介

显示图像的控件,Image控件有多种构造函数:
new Image,用于从ImageProvider获取图像。
new Image.asset,用于使用key从AssetBundle获取图像。
new Image.network,用于从URL地址获取图像。
new Image.file,用于从File获取图像。

为了自动执行像素密度感知资源分辨率,使用AssetImage指定图像,需要确保在控件树中的图片控件上方存在MaterialApp、WidgetsApp和MediaQuery控件。

不同的手机有不同的像素比率,这时就需要根据手机的像素比率来加载不同图片,做法很简单,只需要在图片同级目录下创建2.0x/…和3.0x/…的目录就可以了。

我们在pubspec.yaml这个文件里指定本地图片路径

# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
  1. 实例

  2. 用法

2.2.3 Text

  1. 简介

  2. 实例
    下面的实例有7个不同样式的文本控件:

1 import 'package:flutter/material.dart';2 class TextDemo extends StatelessWidget {3   @override4   Widget build(BuildContext context) {5     return new Scaffold(6       appBar: new AppBar(7         title: new Text('文本控件'),8       ),9       body: new Column(
10         children: <Widget>[
11           new Text(
12             '红色+黑色删除线+25号',
13             style: new TextStyle(
14               color: const Color(0xffff0000),
15               decoration: TextDecoration.lineThrough,
16               decorationColor: const Color(0xff000000),
17               fontSize: 25.0,
18             ),
19           ),
20           new Text(
21             '橙色+下划线+24号',
22             style: new TextStyle(
23               color: const Color(0xffff9900),
24               decoration: TextDecoration.underline,
25               fontSize: 24.0,
26             ),
27           ),
28           new Text(
29             '虚线上划线+23号+倾斜',
30             style: new TextStyle(
31               decoration: TextDecoration.overline,
32               decorationStyle: TextDecorationStyle.dashed,
33               fontSize: 23.0,
34               fontStyle: FontStyle.italic,
35             ),
36           ),
37           new Text(
38             'serif字体+24号',
39             style: new TextStyle(
40               fontFamily: 'serif',
41               fontSize: 26.0,
42             ),
43           ),
44           new Text(
45             'monospace字体+24号+加粗',
46             style: new TextStyle(
47               fontFamily: 'monospace',
48               fontSize: 24.0,
49               fontWeight: FontWeight.bold,
50             ),
51           ),
52           new Text(
53             '天蓝色+25号+2行跨度',
54             style: new TextStyle(
55               color: const Color(0xff4a86e8),
56               fontSize: 25.0,
57               height: 2.0,
58             ),
59           ),
60           new Text(
61             '24号+2个字母间隔',
62             style: new TextStyle(
63               fontSize: 24.0,
64               letterSpacing: 2.0,
65             ),
66           ),
67         ]
68       ),
69     );
70   }
71 }
72 void main() {73   runApp(
74     new MaterialApp(
75       title: 'Flutter教程',
76       home: new TextDemo(),
77     ),
78   );
79 }

运行效果:

3. 用法

2.2.4 Icon

  1. 简介

图标控件,按照IconData中所描述的规则绘制,如Material中预定义的IconDatas。
该控件不可交互,要实现可交互的图标,可以考虑使用Material中的 IconButton。
该控件必须在 Directionality控件里使用,通常这是由WidgetsApp或 MaterialApp自动引入的。详见:https://docs.flutter.io/flutter/widgets/Icon-class.html

  1. 实例

  2. 用法

2.2.5 RaisedButton

  1. 简介

Material Design 风格的浮动按钮,以方形纸片样式悬停在界面上,点击后会产生墨水扩散效果。
避免在dialog和card控件里使用,一般弹出式的控件建议使用扁平化按钮,减少布局层次叠加。详见:https://docs.flutter.io/flutter/material/RaisedButton-class.html

  1. 实例

  2. 用法
    使用时,要实现onPressed回调方法,否则按钮处于禁用状态,默认显示disabledColor样式的扁平化按钮,并且此时更改按钮的颜色不会生效。
    注意该控件的父控件必须是Material控件。
    如果你只需要点击后产生墨水扩散效果,但不想使用按钮,请考虑直接使用InkWell控件。
    如有必要,该按钮将拉伸以适应子控件大小。

2.2.6 Scaffold

  1. 简介

Scaffold 实现了基本的Material Design布局结构。也就是说, MaterialApp 的 child 是 Scaffold Widget。
在Material设计中定义的单个界面上的各种布局元素,在 Scaffold 中都有支持,比如 左边栏(Drawers)、snack bars、以及 bottom sheets。

Scaffold 有下面几个主要属性:

  • appBar:显示在界面顶部的一个 AppBar,也就是 Android 中的 ActionBar 、Toolbar

  • body:当前界面所显示的主要内容 Widget

  • floatingActionButton:Material设计中所定义的 FAB,界面的主要功能按钮

  • persistentFooterButtons:固定在下方显示的按钮,比如对话框下方的确定、取消按钮

  • drawer:侧边栏控件

  • backgroundColor: 内容的背景颜色,默认使用的是 ThemeData.scaffoldBackgroundColor 的值

  • bottomNavigationBar: 显示在页面底部的导航栏

  • resizeToAvoidBottomPadding:类似于 Android 中的 android:windowSoftInputMode=”adjustResize”,控制界面内容 body 是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。

显示 snackbar 或者 bottom sheet 的时候,需要使用当前的 BuildContext 参数调用 Scaffold.of 函数来获取 ScaffoldState 对象,然后使用 ScaffoldState.showSnackBar 和 ScaffoldState.showBottomSheet 函数来显示。

要特别注意 Scaffold.of 的参数 BuildContext, 如果包含该 BuildContext 的 Widget 是 Scaffold 的父 Widget,则 Scaffold.of 是无法查找到对应的 ScaffoldState 对象的,Scaffold.of 返回的是父对象中最近的 Scaffold 中的 ScaffoldState 对象。 比如,如果在 Scaffold 的 build 函数中,使用 build 的 BuildContext 参数是可以的:

 1 @override2 Widget build(BuildContext context) {3   return new RaisedButton(4     child: new Text('SHOW A SNACKBAR'),5     onPressed: () {6       Scaffold.of(context).showSnackBar(new SnackBar(7         content: new Text('Hello!'),8       ));9     },
10   );
11 }
  1. 实例
    如果 build 函数返回一个 Scaffold 对象,则由于 Scaffold 对象是这个 Widget 的子对象,所以使用这个 build 的 BuildContext 参数是不能查找到 ScaffoldState 对象的,这个时候,通过在 Scaffold 中使用一个 Builder 来提供一个新的 BuildConext :
@override2 Widget build(BuildContext context) {3   return new Scaffold(4     appBar: new AppBar(5       title: new Text('Demo')6     ),7     body: new Builder(8       // Create an inner BuildContext so that the onPressed methods9       // can refer to the Scaffold with Scaffold.of().
10       builder: (BuildContext context) {11         return new Center(
12           child: new RaisedButton(
13             child: new Text('SHOW A SNACKBAR'),
14             onPressed: () {15               Scaffold.of(context).showSnackBar(new SnackBar(
16                 content: new Text('Hello!'),
17               ));
18             },
19           ),
20         );
21       },
22     ),
23   );
24 }

另外还可以把 build 函数中的 Widget 分别创建,分别引入新的 BuildContext 来获取 Scaffold。

  1. 用法

2.2.7 Appbar

  1. 简介

AppBar 和 SliverAppBar 是Material Design中的 App Bar,也就是 Android 中的 Toolbar,关于 Toolbar 的设计指南请参考Material Design中 Toolbar 的内容。
AppBar 和 SliverAppBar 都是继承StatefulWidget 类,都代表 Toobar,二者的区别在于 AppBar 位置的固定的应用最上面的;而 SliverAppBar 是可以跟随内容滚动的。

他们的主要属性如下:

  • leading:在标题前面显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮

  • title: Toolbar 中主要内容,通常显示为当前界面的标题文字

  • actions:一个 Widget 列表,代表 Toolbar 中所显示的菜单,对于常用的菜单,通常使用 IconButton 来表示;对于不常用的菜单通常使用 PopupMenuButton 来显示为三个点,点击后弹出二级菜单

  • bottom:一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏

  • elevation:纸墨设计中控件的 z 坐标顺序,默认值为 4,对于可滚动的 SliverAppBar,当 SliverAppBar 和内容同级的时候,该值为 0, 当内容滚动 SliverAppBar 变为 Toolbar 的时候,修改 elevation 的值

  • flexibleSpace:一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样,可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用

  • backgroundColor:APP bar 的颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用

  • brightness:App bar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness

  • iconTheme:App bar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme

  • textTheme: App bar 上的文字样式。默认值为 ThemeData.primaryTextTheme

  • centerTitle: 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样

  1. 实例
import 'package:flutter/material.dart';2 3 class AppBarBottomSample extends StatefulWidget {4   @override5   _AppBarBottomSampleState createState() => new _AppBarBottomSampleState();6 }7 8 class _AppBarBottomSampleState extends State<AppBarBottomSample> with SingleTickerProviderStateMixin {9   TabController _tabController;10 11   @override12   void initState() {13     super.initState();14     _tabController = new TabController(vsync: this, length: choices.length);15   }16 17   @override18   void dispose() {19     _tabController.dispose();20     super.dispose();21   }22 23   void _nextPage(int delta) {24     final int newIndex = _tabController.index + delta;25     if (newIndex < 0 || newIndex >= _tabController.length)26       return;27     _tabController.animateTo(newIndex);28   }29 30   @override31   Widget build(BuildContext context) {32     return new MaterialApp(33       home: new Scaffold(34         appBar: new AppBar(35           title: const Text('AppBar Bottom Widget'),36           leading: new IconButton(37             tooltip: 'Previous choice',38             icon: const Icon(Icons.arrow_back),39             onPressed: () { _nextPage(-1); },40           ),41           actions: <Widget>[42             new IconButton(43               icon: const Icon(Icons.arrow_forward),44               tooltip: 'Next choice',45               onPressed: () { _nextPage(1); },46             ),47           ],48           bottom: new PreferredSize(49             preferredSize: const Size.fromHeight(48.0),50             child: new Theme(51               data: Theme.of(context).copyWith(accentColor: Colors.white),52               child: new Container(53                 height: 48.0,54                 alignment: Alignment.center,55                 child: new TabPageSelector(controller: _tabController),56               ),57             ),58           ),59         ),60         body: new TabBarView(61           controller: _tabController,62           children: choices.map((Choice choice) {63             return new Padding(64               padding: const EdgeInsets.all(16.0),65               child: new ChoiceCard(choice: choice),66             );67           }).toList(),68         ),69       ),70     );71   }72 }73 74 class Choice {75   const Choice({ this.title, this.icon });76   final String title;77   final IconData icon;78 }79 80 const List<Choice> choices = const <Choice>[81   const Choice(title: 'CAR', icon: Icons.directions_car),82   const Choice(title: 'BICYCLE', icon: Icons.directions_bike),83   const Choice(title: 'BOAT', icon: Icons.directions_boat),84   const Choice(title: 'BUS', icon: Icons.directions_bus),85   const Choice(title: 'TRAIN', icon: Icons.directions_railway),86   const Choice(title: 'WALK', icon: Icons.directions_walk),87 ];88 89 class ChoiceCard extends StatelessWidget {90   const ChoiceCard({ Key key, this.choice }) : super(key: key);91 92   final Choice choice;93 94   @override95   Widget build(BuildContext context) {96     final TextStyle textStyle = Theme.of(context).textTheme.display1;97     return new Card(98       color: Colors.white,99       child: new Center(
100         child: new Column(
101           mainAxisSize: MainAxisSize.min,
102           crossAxisAlignment: CrossAxisAlignment.center,
103           children: <Widget>[
104             new Icon(choice.icon, size: 128.0, color: textStyle.color),
105             new Text(choice.title, style: textStyle),
106           ],
107         ),
108       ),
109     );
110   }
111 }
112
113 void main() {114   runApp(new AppBarBottomSample());
115 }

运行效果:


3. 用法

2.2.8 FlutterLogo

  1. 简介
    定义flutter应用的logo,该控件受IconTheme约束。
  2. 实例
import 'package:flutter/material.dart';2 3 void main() {4   runApp(new FadeAppTest());5 }6 7 class FadeAppTest extends StatelessWidget {8   // This widget is the root of your application.9   @override
10   Widget build(BuildContext context) {11     return new MaterialApp(
12       title: 'Fade Demo',
13       theme: new ThemeData(
14         primarySwatch: Colors.blue,
15       ),
16       home: new MyFadeTest(title: 'Fade Demo'),
17     );
18   }
19 }
20
21 class MyFadeTest extends StatefulWidget {22   MyFadeTest({Key key, this.title}) : super(key: key);
23   final String title;
24   @override
25   _MyFadeTest createState() => new _MyFadeTest();
26 }
27
28 class _MyFadeTest extends State<MyFadeTest> with TickerProviderStateMixin {29   AnimationController controller;
30   CurvedAnimation curve;
31
32   @override
33   void initState() {34     controller = new AnimationController(duration: const Duration(milliseconds: 2000), vsync: this);
35     curve = new CurvedAnimation(parent: controller, curve: Curves.easeIn);
36   }
37
38   @override
39   Widget build(BuildContext context) {40     return new Scaffold(
41       appBar: new AppBar(
42         title: new Text(widget.title),
43       ),
44       body: new Center(
45           child: new Container(
46               child: new FadeTransition(
47                   opacity: curve,
48                   child: new FlutterLogo(
49                     size: 100.0,
50                   )))),
51       floatingActionButton: new FloatingActionButton(
52         tooltip: 'Fade',
53         child: new Icon(Icons.brush),
54         onPressed: () {55           controller.forward();
56         },
57       ),
58     );
59   }
60 }
  1. 用法

2.2.9 Placeholder

  1. 简介

占位控件,该控件绘制一个框,表示将来会在该位置添加其他控件。
这个控件在开发过程中很有用,可提示该处接口还没完成。
默认情况下,控件的大小自适应其容器。如果该控件处于无界空间,它将根据给定的fallbackWidth和fallbackHeight自行调整大小。
详见:https://docs.flutter.io/flutter/widgets/Placeholder-class.html

  1. 实例

  2. 用法

2.2.10

  1. 简介

  2. 实例

  3. 用法

3.深入研究

3.1 flutter项目结构分析

  • 纯Flutter项目结构
  • projectName
    -android //android的工程文件
    -build //项目的构建输出文件
    -ios //项目的ios工程文件
    -lib //项目中的dart文件
    -src //包含其他的源文件
    -main.dart //自动生成的项目入口文件
    -test //测试相关的文件
    -assets
    -images//建议存放图片
    -2.0x
    -3.0x
    xxxxx //图片可以直接放到images
    -fonts//建议存放字体
    -pubspec.yaml //项目依赖配置文件
  • 混编Flutter项目

如上图,下面我们就按个来分析,看一下一个flutter混编工程都有那些不同之处相对我们传统的android工程。首先第一个.gradle文件没有区别,里面就是我们当前工程使用的gradle的版本,接下来一个,就是我们的android文件夹,用来存放我们的android工程,再下来是我们的asset文件夹,用来存放flutter工程的资源,包括图片,字体,视频等任何资源文件,http_plugin大家先不看,因为他是一个插件工程,我们最后看,再下来是一个ios文件夹,里面当然是存放我们的ios工程的所有内容,再下来的lib文件夹,则是存放flutter代码的默认目录(可以修改名字,后面详细讲解),最后一个最重要的文件是pubspec.yaml文件,这个文件用来配置flutter工程所需要的依赖等,到这里其实我们就从整体上知道了,flutter工程有那些特别的地方,当然还只是停留在一个整体,下面我们以一张图来进行对比,从整体上我们来看一下与传统android工程的区别。


从图中我们可以看到,其实flutter混编工程无非就是多了下面两部分,很容易理解,因为是跨平台的所以,需要一个ios的容器工程,最后一部分就是flutter工程本身的东西,包括他的资源和代码,以及依赖等。

3.2 flutter项目pubspec.yaml文件

pubspecyaml文件用于配置flutter的资源依赖、库依赖

  • yaml语法
    大小写敏感
    用冒号和缩进代表层次关系
    只能用空格,不能用tab键,对空格多少没要求,同级对齐即可
    可表示三种数据类型,常量值,对象,数组
#即表示url属性值:
url: http://www.wolfcode.cn
#即表示server.host属性的值;
server:host: http://www.wolfcode.cn
#数组,即表示server为[a,b,c]
server:- 120.168.117.21- 120.168.117.22- 120.168.117.23
#常量
pi: 3.14   #定义一个数值3.14
hasChild: true  #定义一个boolean值
name: '你好YAML'   #定义一个字符串
  1. 在dependencies:下添加库依赖
dependencies:flutter:sdk:flutter
#^表示适配和当前大版本一致的版本,即2.x.x都可,~表示适配和当前小版本一致的版本,即2.1.x都可dio:^2.1.0

^表示适配和当前大版本一致的版本,即2.x.x都可,~表示适配和当前小版本一致的版本,即2.1.x都可

  1. 在flutter:下面添加添加资源依赖
flutter:user-material-design:trueassets:- images/lake.jpg- images/light.jpg

冒号后面一定要有空格,表示数组元素的-符号后面也要有空格,否则语法不通过。
images/lake.jpg是图片的路径 即在project下建立一个images文件夹 再把lake.jpg放进去。

3.3 flutter项目图片资源配置

Flutter应用程序可以包含代码和 assets(有时称为资源)。asset是打包到程序安装包中的,可在运行时访问。常见类型的asset包括静态数据(例如JSON文件),配置文件,图标和图片(JPEG,WebP,GIF,动画WebP / GIF,PNG,BMP和WBMP)
资源需要在 pubspec.yaml中配置,配置方法:

flutter:assets:- assets/my_icon.png- assets/background.png
  • Asset 变体(variant)
  1. 变体就是指在构建时,根据不同的场景,选择适应该场景的资源。可以类比Android多图片资源的适配:自动选择加载xxh或者xh下的图片。
  2. 在根据pubspec.yaml构建资源时,会在相邻目录中找到相同名称的任何文件,这些文件会一起打入包中。
应用程序中有如下文件:
assets/image/a.png
assets/image/2x/a.png
assets/image/3x/a.pngpubspec.yaml 中配置:
flutter:
assets:
- assets/calendar.png那么,这三种a.png 都会打入asset bundle中。后面2个被认为是变体。
  • 加载资源

参考文章:http://www.imooc.com/article/278442

Flutter开发实战 高仿微信(二)发现页相关推荐

  1. Flutter开发实战 高仿微信(一)首页

    Flutter开发实战 高仿微信(一)首页 Flutter开发实战 高仿微信(一)首页 flutter 开发微信项目 (一) 1. 开发HomePage页 2. 用到的知识点讲解 2.1 Bottom ...

  2. android+高仿视频录制,android高仿微信视频编辑页

    android高仿微信视频编辑页-视频多张图片提取 上一篇中介绍了有关视频提取图片的知识点,如果对这个不太了解 建议看下android提取视频多张图片和视频信息之前这篇. 这里实现的是仿微信的视频编辑 ...

  3. android高仿微信视频编辑页-视频多张图片提取

    android高仿微信视频编辑页-视频多张图片提取 上一篇中介绍了有关视频提取图片的知识点,如果对这个不太了解 建议看下android提取视频多张图片和视频信息之前这篇. 这里实现的是仿微信的视频编辑 ...

  4. flutter页面布局HTML,Flutter开发实战初级(2)页面布局详解

    初级根底系列 Flutter开发实战初级(1)ListView详解 Flutter开发实战初级(2)布局详解 项目实战系列 Flutter开发实战 高仿微信(1)主页 Flutter开发实战 高仿微信 ...

  5. Kotlin高仿微信-项目实践58篇

    Kotlin高仿微信项目实践主要包含5大模块: 1.Web服务器 2.Kotlin客户端 3.Xmpp即时通讯服务器 4.视频通话服务器 5.腾讯云服务器 另外也有Flutter版本高仿微信功能,Fl ...

  6. Flutter高仿微信-第22篇-支付-二维码收款(二维码)

    Flutter高仿微信系列共59篇,从Flutter客户端.Kotlin客户端.Web服务器.数据库表结构.Xmpp即时通讯服务器.视频通话服务器.腾讯云服务器全面讲解. 详情请查看 效果图: 实现代 ...

  7. Flutter高仿微信-第21篇-支付-向商家付款(二维码)

    Flutter高仿微信系列共59篇,从Flutter客户端.Kotlin客户端.Web服务器.数据库表结构.Xmpp即时通讯服务器.视频通话服务器.腾讯云服务器全面讲解. 详情请查看 效果图: 实现代 ...

  8. Android ActionBar应用实战,高仿微信主界面的设计

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/26365683 经过前面两篇文章的学习,我想大家对ActionBar都已经有一个相对 ...

  9. Flutter高仿微信-项目实践59篇

    Flutter高仿微信(支持Android和IOS系统) Flutter高仿微信主要包含5大模块: 1.Web服务器 2.Flutter客户端 3.Xmpp即时通讯服务器 4.视频通话服务器 5.腾讯 ...

最新文章

  1. 接上篇-找虚拟主机过程
  2. 【Deep Learning笔记】循环神经网络
  3. C语言数组、字符与字符串笔记
  4. 实验人员考评指标_了解实验指标
  5. OpenCV的滤波与卷积
  6. ubuntu 安装java jdk_「ubuntu安装jdk」Ubuntu安装jdk8的两种方式 - seo实验室
  7. 信息学奥赛一本通 1062:最高的分数 | OpenJudge NOI 1.5 05
  8. localstorage存mysql_存储localstorage
  9. Filecoin逻辑梳理及源代码导读
  10. 怎么给没链接的flash加超链接
  11. WinCE OAL中的RAM定制函数
  12. CCCC-GPLT L1-035. 情人节 团体程序设计天梯赛
  13. 3d打印机 模型图纸下载_如何在3D打印机上制作第一个3D模型
  14. 《机器学习实战》 自制勘误表 中文版第一版2015年9月第11次印刷版
  15. 支持向量机_4:Outliers
  16. 嵌入式和物联网有什么关系?一文教你搞明白。
  17. 客户:我考虑一下!销售高手教你该怎么逼单!
  18. 关于文件not found 的几个常见排查点的总结
  19. 优信拍集团php面试题_【优信拍PHP高级工程师面试】优信二手车PHP面试经验。-看准网...
  20. 老网工: 浅谈SDN技术的部署和未来

热门文章

  1. SDU暑期集训排位(5)题解
  2. Python Numpy库教程(超详细)
  3. 【电脑讲解】电脑没有声音了怎么恢复?以win7为例
  4. 宣传海报框架_海报广告位管理 - 简单好用的海报和广告管理工具 – 基于ThinkPHP和Bootstrap的极速后台开发框架...
  5. 日本富士电视台播放“威力棒”专辑引起极大反响
  6. 智慧养殖系统应用现状
  7. Cesium 路径分析(纯前端计算)
  8. 子母系统服务器ip,【腾达 nova mw6 分布式子母路由系统使用总结】设置|操作|网速_摘要频道_什么值得买...
  9. 猜猜盲盒里面有什么!没错!是韭菜!
  10. linux memcached 缓存失效,高并发访问下避免对象缓存失效引发Dogpile效应