www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

学习笔记,我终于迈出了第一步

2020-03-17 06:04 来源:未知

时间: 2019-12-27阅读: 71标签: Flutter作者:星星y,链接:哎,Flutter真香啊

  1. 有动静widget:StatefulWidget和无状态widget:StatelessWidget 前面一个无需贯彻Widget build(BuildContext context卡塔尔国。

    实际的抉择决定于widget是或不是须求管住一些情景

  2. 在Dart语言中运用下划线前缀标记符,会免强其变成私有的。

  3. Icons.favorite Icons类里面有成都百货上千默许Logo

  4. isOdd 是不是奇数 2.isOdd -> false 1.isOdd -> true

  5. pushSaved “”发轫的自行转成私有

  6. 导航栏增多开关和事件

Flutter的境况搭配完事后,就开首Flutter的开采,上面包车型地铁片段工具和艺术,能够省下某些时光。

早在一年前想上学下flutter,但登时对于它构造中鬼世界式的嵌套有一点触目惊心,心想怎么嵌套这么复杂,就未有xml结构格局吗,用jsx形式也行啊,为啥要用dart而不用javascript,走开,劳方和资方不学了。

协调在用的,近年来想到的,正是那一个了,计算一下。

但是,随着二零一七年google io大会flutter新版本发布,大势宣扬。笔者又起来上马学习flutter了:

 @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('Startup Name Generator'), actions: <Widget>[ // AppBar 添加一个按钮 样式为list 事件是_pushSaved new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved) ], ), body: _buildSuggestions; } // tooltip 长时间按下的提示文字 IconButton(icon: new Icon(Icons.search), tooltip: 'Search', onPressed: null) 

1.JSON拆解剖析快快速生成成实体类

依附接口再次回到的多寡,编写实体类,加多多少个点子。

fromJson(State of Qatar方法是可以聪多少个Map中布局出一个User的实例,toJson(State of Qatar方法,可以将一个实例转变为Map。

图片 1image.png

假定接口重返的数目相比复杂点,那么手动写起来就能很麻烦。那时能够应用json_serializable来帮你自动生成实体类的一部分代码,还会有使用caijinglong.github.io/json2dart/i…来快速变动相关代码。

将json数据复制到那一个网址上,就能够变卦相关的代码,只须要将那几个代码复制到项目中的文件就能够了,

最终在我们的体系根目录下运作flutter packages pub run build_runner build,大家能够在必要时为大家的model生成json系列化代码 。

瞩目:要先在pubspec.yaml文件之中增加:

图片 2image.png

种种类最后边生成的with _$UserSerializerMixin,这一部分可以去掉,不去掉的话,好像生成会有题目,反正笔者是去掉了,没什么影响。

图片 3image.png

浏览浏览

  1. 分界面跳转方式

2.代码模板

最简便易行的二个例子,就是在写三个有境况StatefulWidget的时候,要手动世袭StatefulWidget,重写createState方法,再创建三个应和的State类因人而异写build方法。会写到你健忘。

其偶尔候就供给有的代码模板,帮你快速生成代码。

左右百度时而毫无疑问有个别导入Flutter代码模板的课程。

举个例子直接打出stf,就足以自动唤醒生成StatefulWidget的代码了。

图片 4image.png

本想看下摄像实战的,前边开采功效太低(有一点啰嗦),甩掉了。最后照旧调节通过翻阅flutter项目源码学习,事实上照旧这种频率最高。

3.Asset能源文件的导入

Flutter中,多如牛毛类型的asset包罗静态数据,配置文件,Logo和图表(JPEG,WebP,GIF,动漫WebP / GIF,PNG,BMP和WBMP)。

相符导入的能源都要在pubspec.yaml文件中固守上边包车型的士措施,八个贰个拓宽宣示,应用程序工夫取得到。

图片 5image.png

矫正措施:要饱含asset文件下边包车型地铁兼具财富,直接用上边那样方法,那样的话,只在这里个目录里的文件会被含有进来。

图片 6image.png

适逢其会公司有新app开拓,本次决定用flutter开采了,边开荒边上学,既完结了办事又形成了就学(ps:现在商家ios和前端也在学了:joy:)。

 Navigator.of.push( new MaterialPageRoute( builder:  { }, ), );

4.Flutter Outline工具,首要用以视图的预览,还会有其余作用

在编排结构的时候,能够观望Flutter Outline分界面,会实时地修正所写的布局档案的次序,方便查看。

除却视图的预览,还会有其余的效果与利益。

正是右键某二个widget,能够依照提醒框,神速帮您在这里个widget的外部包裹一层举例padding之类的代码。这么些效果有的时候候挺方便的。

图片 7image.png

Extract method的效果是:能够把某八个widget控件的代码,帮你封装成一个艺术。不用您去手动地去找寻壹个widget的任何代码,再自身拉到某四个办法内。

贰头,也得以平价地看见这一个widget的有关代码,举个例子要复制操作起来也相比较平价。

图片 8image.png

用完flutter的感触是,一旦接收这种嵌套布局后,开采布局也没那么难,hot reload牛皮,async真好用,dart语言真方便,嗯,香啊。

  1. 一行函数写法

5.拖动widget自动生成相关代码

有四个网站:flutterstudio.app/

可以拖动widget到模拟器中,就足以生成相关的布局代码,本身手动复制粘贴就能够了。

图片 9image.png图片 10image.png

加群 Android IOC布局划杜撰计领取到手往期Android高端布局资料、源码、笔记、录制。高级UI、品质优化、结构师课程、NDK、混合式开垦(ReactNative Weex)微信小程序、Flutter全方面包车型地铁Android晋级实施手艺,群内还应该有本事大腕一齐座谈调换解决问题。

图片 11image

上边就本次app开荒记录相关要点(新手阶段,招待指正)

领取方式:

其三方库

 // 多行 void main() { runApp( new Center( child: new Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ) ) } // 一行 void main() => runApp(new MyApp;
点赞 加群免费获取 Android IOC布局划虚构计

dio: 网络

  1. // Material 是UI呈现的“一张纸”

  2. 请确认保障在pubspec.yaml文件中,将flutter的值设置为:uses-material-design: true。那允许大家得以行使一组预订义Material icons。

  3. Row和Column

sqflite: 数据库

pull_to_refresh: 下拉刷新,上拉加载

 child: new Row( children: <Widget>[ new ..., new ..., new ..., ], )

 child: new Column( children: <Widget>[ new ..., new ..., new ..., ], ),

json_serializable: json连串化,自动生成model工厂方法

  1. cached_network_image 图片占位和淡入淡出

  2. push

shared_preferences: 本地存款和储蓄

fluttertoast: 吐司新闻

 Navigator.push( context, new MaterialPageRoute(builder:  => new 新界面), ); // 如果需要传值: 新界面({Key key, @required this.接收字段的名字}) : super; pop Navigator.pop;

图形财富

  1. dio网络恳求

  2. import 'dart:convert'; // package将响应内容转变为三个json Map

  3. // 使用fromJson工厂函数,将json Map 转变为三个Post对象

为适配各种分辨率的图纸能源,通常需求1,2,3倍的图。在flutter项目根目录下创立assets/images目录,在pubspec.yaml文件中参与图片配置

flutter: # ... assets: - assets/images/
new Post.fromJson;

下一场经过sketch切出1/3/3倍图片,这里可透过编写制定预设,在词首到场2.0x/和3.0x/,那样导出的格式便符合flutter图片能源所需了。

  1. future参数是一个异步的网络央求

  2. import 'dart:io'; // 增添需要的headers

  3. // 长连接

此间再建贰个image_helper.dart的工具类,用于发生Image

class ImageHelper { static String png(String name) { return "assets/images/$name.png"; } static Widget icon(String name, {double width, double height, BoxFit boxFit}) { return Image.asset( png(name), width: width, height: height, fit: boxFit, ); }}
import 'package:web_socket_channel/io.dart';import 'package:multi_server_socket/multi_server_socket.dart';

主界面Tab导航

  1. // 网络乞求

在app主界面,tab底部导航是最常用的。平时依照Scaffold的bottomNavigationBar配和PageView使用。通过PageController调整PageView分界面切换,同一时间接选举用BottomNavigationBar的currentIndex调节tab选中状态。

为了能使监听重临键,使用WillPopScope落成点若干回重返键退出app。

Future<Post> fetchPost() async { final response = await http.get('[http://jsonplaceholder.typicode.com/posts/1](http://jsonplaceholder.typicode.com/posts/1)'); final responseJson = json.decode(response.body); return new Post.fromJson(responseJson);}// 请求添加headers/*Future<Post> fetchPost() async { final response = await http.get( '[https://jsonplaceholder.typicode.com/posts/1](https://jsonplaceholder.typicode.com/posts/1)', headers: {HttpHeaders.AUTHORIZATION: "Basic your_api_token_here"}, ); final json = jsonDecode(response.body); return new Post.fromJson;}*/new FutureBuilder<Post>( future: fetchPost(), builder: (context, snapshot) { return new CircularProgressIndicator
List pages = Widget[HomePage(), MinePage()];class _TabNavigatorState extends StateTabNavigator { DateTime _lastPressed; int _tabIndex = 0; var _controller = PageController(initialPage: 0); BottomNavigationBarItem buildTab( String name, String normalIcon, String selectedIcon) { return BottomNavigationBarItem( icon: ImageHelper.icon(normalIcon, width: 20), activeIcon: ImageHelper.icon(selectedIcon, width: 20), title: Text(name)); } @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: BottomNavigationBar( currentIndex: _tabIndex, backgroundColor: Colors.white, onTap: (index) { setState(() { _controller.jumpToPage(index); _tabIndex = index; }); }, selectedItemColor: Color(0xff333333), unselectedItemColor: Color(0xff999999), selectedFontSize: 11, unselectedFontSize: 11, type: BottomNavigationBarType.fixed, items: [ buildTab("Home", "ic_home", "ic_home_s"), buildTab("Mine", "ic_mine", "ic_mine_s") ]), body: WillPopScope( child: PageView.builder( itemBuilder: (ctx, index) = pages[index], controller: _controller, physics: NeverScrollableScrollPhysics(),//禁止PageView左右滑动 ), onWillPop: () async { if (_lastPressed == null || DateTime.now().difference(_lastPressed)  Duration(seconds: 1)) { _lastPressed = DateTime.now(); Fluttertoast.showToast(msg: "Press again to exit"); return false; } else { return true; } }), ); }}
  1. 长连接

互连网层封装

网络框架使用的是dio,不管是哪一种平台,互联网供给最后要转成实体model用于ui体现。这里先将dio做四个包装,便于使用。

// 连接长连接IOWebSocketChannel.connect('[ws://echo](ws://echo/).[websocket.org](http://websocket.org/)’)// 接收消息new StreamBuilder( stream: widget.channel.stream, builder: (context, snapshot) { return new Padding( child: new Text(snapshot.hasData ? '${snapshot.data}' : ''), padding: const EdgeInsets.symmetric(vertical: 20.0) ); })// 发送消息widget.channel.sink.add(_textController.text);// 关闭长连接widget.channel.sink.close();

通用拦截器

  1. 在Flutter中加多能源和图表

网络央浼中习见供给增多自定义拦截器来预管理网络乞求,往往供给将登入新闻(如user_id等)放在公共参数中,比如;

import 'package:dio/dio.dart';import 'dart:async';import 'package:shared_preferences/shared_preferences.dart';class CommonInterceptor extends Interceptor { @override Future onRequest(RequestOptions options) async { options.queryParameters = options.queryParameters ?? {}; options.queryParameters["app_id"] = "1001"; var pref = await SharedPreferences.getInstance(); options.queryParameters["user_id"] = pref.get(Constants.keyLoginUserId); options.queryParameters["device_id"] = pref.get(Constants.keyDeviceId); return super.onRequest(options); }}
  1. 标准widget:

Dio封装

接下来利用dio封装get和post央浼,预管理响应response的code。假如我们的响应格式是那样的:

Container添加 padding, margins, borders, background color, 或将其他装饰添加到widget.GridView将 widgets 排列为可滚动的网格.ListView将widget排列为可滚动列表Stack将widget重叠在另一个widget之上.Material Components:Card将相关内容放到带圆角和投影的盒子中。ListTile将最多3行文字,以及可选的行前和和行尾的图标排成一行
{ code:0, msg:"获取数据成功", result:[] //或者{}}

import 'package:dio/dio.dart';import 'common_interceptor.dart';/* * 网络管理 */class HttpManager { static HttpManager _instance; static HttpManager getInstance() { if (_instance == null) { _instance = HttpManager(); } return _instance; } Dio dio = Dio(); HttpManager() { dio.options.baseUrl = ""; dio.options.connectTimeout = 10000; dio.options.receiveTimeout = 5000; dio.interceptors.add(CommonInterceptor()); dio.interceptors.add(LogInterceptor(responseBody: true)); } static FutureMapString, dynamic get(String path, MapString, dynamic map) async { var response = await getInstance().dio.get(path, queryParameters: map); return processResponse(response); } /* 表单形式 */ static FutureMapString, dynamic post(String path, MapString, dynamic map) async { var response = await getInstance().dio.post(path, data: map, options: Options( contentType: "application/x-www-form-urlencoded", headers: {"Content-Type": "application/x-www-form-urlencoded"})); return processResponse(response); } static FutureMapString, dynamic processResponse(Response response) async { if (response.statusCode == 200) { var data = response.data; int code = data["code"]; String msg = data["msg"]; if (code == 0) {//请求响应成功 return data; } throw Exception(msg); } throw Exception("server error"); }}
  1. pubspec.yaml中加多字体 注意缩进对齐 注意缩进对齐 注意缩进对齐

map转model

选择dio可以将最终的伏乞响应response转成MapString, dynamic对象,大家还须求将map转成相应的model。要是大家有三个获得小说列表的接口响应如下:

-asset 路径是与pubspec.yaml平级的文件路径flutter: # Include the Material Design fonts. uses-material-design: true fonts: - family: Rock Salt fonts: # [https://fonts.google.com/specimen/Rock Salt](https://fonts.google.com/specimen/Rock Salt) - asset: fonts/Arial-Unicode.ttf - family: VT323 fonts: # [https://fonts.google.com/specimen/VT323](https://fonts.google.com/specimen/VT323) - asset: fonts/Arial-Unicode.ttf - family: Ewert fonts: # [https://fonts.google.com/specimen/Ewert](https://fonts.google.com/specimen/Ewert) - asset: fonts/Ewert-Regular.ttf
{ code:0, msg:"获取数据成功", result:[ { article_id:1, article_title:"标题", article_link:"" } ]}
  1. 比如二个关门按键在

就供给叁个Article的model。由于Flutter下是禁止使用反射的,大家只能手动起头化各类成员变量。

唯独我们得以经过json_serializable将手动初阶化的专门的职业交给它。首先在pubspec.yaml引进它:

new Row(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ new FlatButton(onPressed: () { }, child: Icon(Icons.close))],);
dependencies: json_annotation: ^2.0.0dev_dependencies: json_serializable: ^2.0.0
  1. 分割线

咱俩成立贰个article.dart的model类:

import 'package:json_annotation/json_annotation.dart';part 'article.g.dart';//FieldRename.snake 表示json字段下划线分割类型如:article_id@JsonSerializable(fieldRename: FieldRename.snake, checked: true)class Article { final int articleId; final String articleTitle; final String articleLikn;}
new Divider(color: Colors.lightBlue,) 

潜心这里援引到了贰个article.g.dart未有发出的公文,大家由此pub run build_runner build命令就能够转移这几个文件

  1. 自定义Icon
// GENERATED CODE - DO NOT MODIFY BY HANDpart of 'article.dart';// **************************************************************************// JsonSerializableGenerator// **************************************************************************Article _$ArticleFromJson(MapString, dynamic json) { return $checkedNew('Article', json, () { final val = Article(); $checkedConvert(json, 'article_id', (v) = val.articleId = v as int); $checkedConvert( json, 'article_title', (v) = val.articleTitle = v as String); $checkedConvert(json, 'article_link', (v) = val.articleLink = v as String); return val; }, fieldKeyMap: const { 'articleId': 'article_id', 'articleTitle': 'article_title', 'articleLink': 'article_link' });}MapString, dynamic _$ArticleToJson(Article instance) = String, dynamic{ 'article_id': instance.articleId, 'article_title': instance.articleTitle, 'article_link': instance.articleLink };

下一场在article.dart里增添工厂方法

new Image.asset(“图片路径", width: 20.0, height: 20.0,)
class Article{ ... factory Article.fromJson(MapString, dynamic json) = _$ArticleFromJson(json);}
  1. 开关宽高

切切实实央浼封装

创设好model类后,就能够建七个具体的api诉求类ApiRepository,通过async库,能够将网络诉求最后封装成一个Future对象,实际调用时,大家得以将异步回调情势的央浼转成同步的花样,那有一点和kotlin的协程相通:

001、new Padding(padding: new EdgeInsets.fromLTRB(48.0, 20.0, 48.0, 20.0), child: new Row( children: <Widget>[ new Expanded(child: new RaisedButton(onPressed: (){ }, //设置控件的高度 child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: new Text("登录", style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ), ), ], ),),002、new Container( width: MediaQuery.of.size.width - 48 * 2 , padding: new EdgeInsets.only(top: 40.0), child: new RaisedButton(onPressed: (){ }, //设置控件的高度 child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: new Text("登录", style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ),),003、Widget _bigButton(String text, double lSpace, double rSpace) { return new Container( width: MediaQuery.of.size.width - lSpace - rSpace, height: 48.0, margin: new EdgeInsets.only(left: lSpace, right: rSpace), color: Colors.white54, padding: new EdgeInsets.only, child: new RaisedButton(onPressed: (){ print; }, child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), child: new Text(text, style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ), );}
import 'dart:async';import '../_manager.dart';import '../model/article.dart';class ApiRepository { static FutureListArticle articleList() async { var data = await HttpManager.get("articleList", {"page": 1}); return data["result"].map((MapString, dynamic json) { return Article.fromJson(json); }); }}
  1. 设施尺寸

实质上调用

装进好网络央求后,就能够在切实的机件中应用了。假如有八个_ArticlePageState:

MediaQuery.of.size.width
import 'package:flutter/material.dart';import '../model/article.dart';import '../repository/api_repository.dart';class ArticlePage extends StatefulWidget { @override StateStatefulWidget createState() { return _ArticlePageState(); }}class _ArticlePageState extends StateArticlePage { ListArticle _list = []; @override void initState() { super.initState(); _loadData(); } void _loadData() async {//如果需要展示进度条,就必须try/catch捕获请求异常。 showLoading(); try { var list = await ApiRepository.articleList(); setState(() { _list = list; }); } catch (e) {} hideLoading(); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: ListView.builder( itemCount: _list.length, itemBuilder: (ctx, index) { return Text(_list[index].articleTitle); })), ); }}
  1. 设施像素密度

数据库

数据库操作通过sqflite,简单包装处理事例了文章阿特icle的插入操作。

MediaQuery.of.devicePixelRatio
import 'package:sqflite/sqflite.dart';import 'package:path/path.dart';import 'dart:async';import '../model/article.dart';class DBManager { static const int _VSERION = 1; static const String _DB_NAME = "database.db"; static Database _db; static const String TABLE_NAME = "t_article"; static const String createTableSql = ''' create table $TABLE_NAME( article_id int, article_title text, article_link text, user_id int, primary key(article_id,user_id) ); '''; static init() async { String dbPath = await getDatabasesPath(); String path = join(dbPath, _DB_NAME); _db = await openDatabase(path, version: _VSERION, onCreate: _onCreate); } static _onCreate(Database db, int newVersion) async { await db.execute(createTableSql); } static Futureint insertArticle(Article item, int userId) async { var map = item.toMap(); map["user_id"] = userId; return _db.insert("$TABLE_NAME", map); }}
  1. 情况栏中度

Android层包容通讯管理

为了合营底层,需求通过MethodChannel举办Flutter和Native(Android/iOS卡塔尔通信

MediaQuery.of.padding.top

flutter调用Android层方法

  1. 操心键盘挡住控件,能够利用 SingleChildScrollView,将SingleChildScrollView充任容器。

  2. 一个至上轻便分界面

此间比如flutter端展开系统相册意图,并获得最终的相册路径回调给flutter端。

咱俩在Android中的MainActivity中onCreate方法管理通讯逻辑

import 'package:flutter/material.dart';class RegisterPage extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( backgroundColor: Colors.black, body: new RegisterWidget; }}class RegisterWidget extends StatefulWidget { RegisterWidgetState createState() => RegisterWidgetState();}class RegisterWidgetState extends State<RegisterWidget> { @override Widget build(BuildContext context) { return new Text("RegisterPage", style: TextStyle(color: Colors.white),); }}
eventChannel = MethodChannel(flutterView, "event") eventChannel?.setMethodCallHandler { methodCall, result - when (methodCall.method) { "openPicture" - PictureUtil.openPicture(this) { result.success(it) } } }
  1. Flutter 按键总计

因为是通过result.success将结果回调给Flutter端,所以封装了张开相册的工具类。

object PictureUtil { fun openPicture(activity: Activity, callback: (String?) - Unit) { val f = getFragment(activity) f.callback = callback val intentToPickPic = Intent(Intent.ACTION_PICK, null) intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*") f.startActivityForResult(intentToPickPic, 200) } private fun getFragment(activity: Activity): PictureFragment { var fragment = activity.fragmentManager.findFragmentByTag("picture") if (fragment is PictureFragment) { } else { fragment = PictureFragment() activity.fragmentManager.apply { beginTransaction().add(fragment, "picture").commitAllowingStateLoss() executePendingTransactions() } } return fragment }}
· InkWell // 纯文字按钮· OutLineButton // 边框按钮· IconButton // icon按钮· 

然后在PictureFragment中到场callback,况兼管理onActivityResult逻辑

  1. import 'package:flutter/services.dart';
class PictureFragment : Fragment() { var callback: ((String?) - Unit)? = null override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 200) { if (data != null) { callback?.invoke(FileUtil.getFilePathByUri(activity, data!!.data)) } } }}

此处FileUtil.getFilePathByUri是通过data获取相册路线逻辑就不贴代码了,互连网海人民广播广播台湾大学得以找出一下。

TextFieldinputFormatters: <TextInputFormatter> [ WhitelistingTextInputFormatter.digitsOnly,],

然后在flutter端使用

  1. 如桃月经增加简书

  2. 验证码开关

void _openPicture() async { var result = await MethodChannel("event").invokeMethod("openPicture"); images.add(result as String); setState(() {}); }

Android端调用Flutter代码

new Positioned( child: new Container( width: 80.0, height: 27.0, alignment: Alignment.center, decoration: new BoxDecoration( border: new Border.all( color: Colors.white, width: 1.0, ), borderRadius: new BorderRadius.circular, child: InkWell( child: _mText(_verifyStr, 12.0), onTap: , )),

将刚刚MainActivity中的eventChannel注解成类变量,就能够在其余地方使用它了。譬如推送公告,如若急需调用Flutter端的埋点接口方法。

  1. 倒计时艺术
class MainActivity : FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) GeneratedPluginRegistrant.registerWith(this) eventChannel = MethodChannel(flutterView, "event") eventChannel?.setMethodCallHandler { methodCall, result - ... } } checkNotify(intent) initPush() } companion object { var eventChannel: MethodChannel? = null }}

在Firebase音信布告中调用Flutter方法

@overridevoid dispose() { super.dispose(); _cancelTimer();}_startTimer() { if (_verifyStr == '重新发送' || _verifyStr == '获取验证码') { _seconds = 5; _timer = new Timer.periodic(new Duration(seconds: 1),  { if (_seconds == 0) { _cancelTimer(); return; } _seconds--; _verifyStr = '$_seconds'; setState; if (_seconds == 0) { _verifyStr = '重新发送'; } }); }}_cancelTimer() { _timer?.cancel();}
class FirebaseMsgService : FirebaseMessagingService() { override fun onMessageReceived(msg: RemoteMessage?) { super.onMessageReceived(msg) "onMessageReceived:$msg".logE() if (msg != null){ showNotify(msg) MainActivity.eventChannel?.invokeMethod("saveEvent", 1) } }}
  1. 富文本拼接: 左券

下一场在Flutter层大家抬高回调

class NativeEvent { static const platform = const MethodChannel("event"); static void init() { platform.setMethodCallHandler(platformCallHandler); } static Futuredynamic platformCallHandler(MethodCall call) async { switch (call.method) { case "saveEvent": print("saveEvent....."); await ApiRepository.saveEventTracking(call.arguments); return ""; break; } }}
Widget _protocolWidget() { return new Container( child: new Row( children: <Widget>[ new GestureDetector( onTap: () { print; }, child: Icon(Icons.add_alert, color: Colors.white), ), new Text.rich( new TextSpan( text: '我已阅读并同意', style: new TextStyle( fontSize: 12.0, color: Colors.grey[500], fontWeight: FontWeight.w400, ), children: [ new TextSpan( recognizer: new TapGestureRecognizer() ..onTap = () { print("《燎原用户服务协议》"); }, text: "《燎原用户服务协议》", style: new TextStyle( fontSize: 14.0, color: Color(0XFFB57A36), fontWeight: FontWeight.w400, ), ) ] ) ), ], ) );}
  1. 阴影、圆角
new Card( elevation: 4.0, shape: new RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular, topRight: Radius.circular, bottomLeft: Radius.circular, bottomRight: Radius.circular, child: new IconButton(icon: Icon(Icons.add), onPressed: 
  1. YYTabbarWidget
import 'package:flutter/material.dart';// with AutomaticKeepAliveClientMixinclass YYTabbarWidget extends StatefulWidget { List<Widget> tabItems = []; Widget title; List<Widget> tabViews = []; PageController pageController; final ValueChanged<int> onPageChanged; final Widget drawer; YYTabbarWidget({Key key, this.drawer, this.tabItems, this.title, this.tabViews, this.pageController, this.onPageChanged, }) : super; _YYTabbarWidgetState createState() => _YYTabbarWidgetState(drawer, title, tabItems, tabViews, pageController, onPageChanged);}class _YYTabbarWidgetState extends State<YYTabbarWidget> with SingleTickerProviderStateMixin { final Widget _title; final List<Widget> _tabViews; final List<Widget> _tabItems; final ValueChanged<int> _onPageChanged; final Widget _drawer; _YYTabbarWidgetState( this._drawer, this._title, this._tabItems, this._tabViews, this._pageController, this._onPageChanged, ) : super(); TabController _tabController; PageController _pageController; @override void initState() { super.initState(); _tabController = new TabController(length: _tabItems.length, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } _renderTab() { print(_tabItems); List<Widget> list = new List(); for (int i = 0; i < _tabItems.length; i  ) { list.add(new FlatButton(onPressed: () { print; _pageController.jumpTo(MediaQuery .of .size .width * i); }, child: _tabItems[I], ) ); } return list; } @override Widget build(BuildContext context) { return new Scaffold( drawer: _drawer, appBar: new AppBar( title: _title, ), body: new PageView( controller: _pageController, children: _tabViews, onPageChanged:  { _tabController.animateTo; _onPageChanged?.call; }, ), bottomNavigationBar: new Material( color: Colors.white, child: new TabBar( indicatorPadding: new EdgeInsets.only, controller: _tabController, tabs: _renderTab(), indicatorColor: Colors.red, ), ), ); }}
  1. ListView 增加刷新,当数码少的时候不能滚动
physics: new AlwaysScrollableScrollPhysics(), // 让ListView一直可以滚动
  1. tabView切换 子分界面都会调用initState
解决:AutomaticKeepAliveClientMixinclass HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true;}
  1. 路有跳转
///不带参数的路由表跳转Navigator.pushNamed(context,routeName);///跳转新页面并且替换,比如登录页跳转主页Navigator.pushReplacementNamed(context,routeName);///跳转到新的路由,并且关闭给定路由的之前的所有页面Navigator.pushNamedAndRemoveUntil(context,'/calendar',ModalRoute.withName;///带参数的路由跳转,并且监听返回Navigator.push(context,newMaterialPageRoute(builder:=>newNotifyPage.then{ ///获取返回处理 });
  1. flutter lib
cupertino_icons: ^0.1.2 #iconflutter_spinkit: "^2.1.0" # load more loading import 'package:flutter_spinkit/flutter_spinkit.dart';dio: x.x.x #无网络请求 import 'package:dio/dio.dart';
  1. dio互连网央求示例
_dioRequest() async { Dio dio = new Dio(); Response response; try { String url; var params; // 请求参数 Options options; // 配置:超时,请求头,请求类型等 response = await dio.request(url, data: params, options: options); } on DioError catch { // 请求出错时,返回一个DioError对象 }}
  1. build_runner的使用
1、在根目录运行2、一次性创建.g.dart文件 使用build 此时目录内不能有.g.dart文件3、watch是监听 有model类的文件创建 自动创建.g.dart文件flutter packages pub run build_runner buildflutter packages pub run build_runner watch
TAG标签:
版权声明:本文由澳门新葡8455手机版发布于Web前端,转载请注明出处:学习笔记,我终于迈出了第一步