该文章主要讲述自己两个月以来 通过闲暇时间编写 简单学习Dart 和 编写 Flutter 的知识点总结和心得,可能不够系统并且有点乱。仅供个人回忆和思考。
update time 2019年10月25日21:28:53
备注: Flutter 中万物皆为 Widget
这边我主要通过 Flutter 中文官网学习 Flutter 中文官网
学习Dart 中 主要查阅的中文博客 Dart 讲解
上述文章 已经将Dart 基础讲解的很透彻了,相信学习过java 和 kotlin 的您应该很好上手。
本人mac 所以 参考的是 Mac 配置Flutter 配置 。
因为需要 Xcode 所以对Mac 是有一定要求的。
在Flutter 中一切都是 Widget ,接下来我将通过自己编写商城的 两个月时间学到的东西简单的进行一次总结。
本人Flutter 商城GitHub 地址
注 :build中设置 debugShowCheckedModeBanner: false, 可以去掉右上角 Debug标签
在欢迎界面中 使用runApp() 来设置app 的启动首页,我在这里使用了 动画来完成 欢迎界面的 动画 及结束事件。
因为欢迎界面存在变动的 View,则我们创建的时候需要使用 快捷键 ‘stful’ 来创建 StatefulWidget,
部分代码
// 动画的声明
AnimationController controller;
Animation animation;
// 一般在初始化/设置状态 的时候使用
@override
void initState() {
super.initState();
controller = AnimationController(vsync:this,duration:Duration(milliseconds:2000));
animation = Tween(begin: 0.0,end:1.0).animate(controller);
/// 检测动画结束,就跳转到首页
animation.addStatusListener((status){
if(status == AnimationStatus.completed){
// 页面的跳转
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context)=>MyApp()),
(route)=> route==null);
}
});
/// 开始动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: animation,
child: Image.network( //网络图片
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec='
'1546851657199&di=fdd278c2029f7826790191d59279dbbe&imgtype=0&src='
'http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F0112cb554438090000019ae93094f1.jpg'
'%401280w_1l_2o_100sh.jpg',
scale: 2.0, //进行缩放
fit:BoxFit.cover // 充满父容器
),
);
}
由于首页采用 四个分页,这里选择了BottomNavigationBarItem ,由于需要时刻保持界面变化 及View 的修改,这里引入 第三方库 ’Provide‘ 用来保存状态
Provide 初始化部分
// Provide初始化部分需要放在 main()函数中
var currentIndexProvide = CurrentIndexProvide();
var providers =Providers();
providers.provide(Provider.value(currentIndexProvide));
runApp(ProviderNode(child: SplashPage(), providers: providers));
Provide 声明部分
class CurrentIndexProvide with ChangeNotifier{
int currentIndex=0;
changeIndex(int newIndex){
currentIndex=newIndex;
notifyListeners();
}
}
上文我们已经简单设置编写了 Flutter 中的状态管理,这里我们就可以学习状态的另外一种用法(代码注释中也会介绍 另一个第三方库 主要用于界面的适配 ‘ScreenUtil’ )
首页部分主要代码
// 界面
final List<Widget> tabBodies = [
HomePage(),CategoryPage(),CartPage(),MemberPage()];
@override
Widget build(BuildContext context) {
///初始化 宽高适配工具
ScreenUtil.instance = ScreenUtil(width: 750, height: 1280)..init(context);
// Provide的使用 可以在CurrentIndexProvide 数据发生变化时候实时更新
return Provide<CurrentIndexProvide>(
builder: (context, child,value,){
int currentIndex= Provide.value<CurrentIndexProvide>(context).currentIndex;
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: currentIndex,
items: bottomBars,
onTap: (index){
/// 改变 Provide 下标状态
Provide.value<CurrentIndexProvide>(context).changeIndex(index);
},
),
/// 为了可以保存状态 需要嵌套一个 IndexedStack (堆栈需要 传入tab列表和下标)
body: IndexedStack(
index: currentIndex,
/// 列表需要的对象是 list 需要及时更正对象类型是否正确
children: tabBodies
)
);
}
);
}
indexPage 界面简单就这样。(如果有不懂得可以移步到 Github 中查看代码)
其实首页 分类 购物车更多的 就是 布局的编写、业务逻辑的编写和 对js胖提供的json 数据解析展示。
body:FutureBuilder(
future: getHomePageContent(),
builder: (context,snapshot){
if(snapshot.hasData){
var data=json.decode(snapshot.data.toString());
print('总体数据${data['data']}');
/// 获取轮播图资源
List<Map> swiperDataList = (data['data']['slides'] as List).cast();
/// 获取类别列表
List<Map> navigatorList =(data['data']['category'] as List).cast();
List<Map> recommendList = (data['data']['recommend'] as List).cast(); // 商品推荐
/// ScrollView 同android => 改为 EasyRefresh ,可提供上拉加载更多
return EasyRefresh(
footer: MaterialFooter(
backgroundColor: Colors.white,
),
child: ListView(
children: <Widget>[
SwiperDiy(swiperDataList:swiperDataList ), //页面顶部轮播组件
TopNavigator(navigatorList:navigatorList), //导航组件
AdBanner(advertesPicture : advertesPicture), //广告组件
LeaderPhone(leaderImage:leaderImage,leaderPhone: leaderPhone), // 拨打电话
Recommend(recommendList:recommendList),// 推荐列表
/// 热门商品 列表部分
hotTitle,
_hotWrapList(),
],
),
onLoad: () async {
print('上拉记载更多:pageindex:$page');
_getHotGoods();
},
);
}else{
return Center(
child: Text('加载中'),
);
}
},
)
上述代码中我么您使用到了 上拉加载,下拉刷新的控件 ‘EasyRefresh’ ,通过 ‘onLoad’ 的方法来加载 下一页数据。顶部的 滑动控件用的第三方的 ‘Swiper’。
导航界面使用的组合是 GridView ,item 中通过 InkWell 包裹Child,可以添加OnTap 方法。
联系店长 这一块主要就是一个图片,但是点击图片后 引用第三方库 ‘url_launcher’ 可以实现拨打电话的功能,真机可以已测试,模拟器可能不行。
分类界面由于有 一级 和二级 分类,所以这里左侧使用的 ListView 。右侧顶部 则使用的 横向的 ListView ,
// listview 方向设置
scrollDirection: Axis.horizontal,
在列表中 也要制造分割线 介绍新的控件使用方法
return Container(
height: ScreenUtil().setHeight(90),
width: ScreenUtil().setWidth(570),
// 设置底部 分割线
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(width: 0.2,color: Colors.black12)
)
),
child: ListView.builder(
itemCount: childCategory.childCategoryList.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index){
return _rightInkWell(index,childCategory.childCategoryList[index]);
}
),);
根据 json 实现 一级列表和 二级列表的联动,剩下的就是展示商品信息的 右下方 商品详情列表,因为存在上拉加载更多的选项,我们依然采用‘Expanded’ 来展示数据。
从项目的效果图不难看出,顶部我们直接就是一个 Image 来展示 商品的 大图,下方则为 几个Text,在下边则为两个状态的 Tab,我们这里使用 自定义的 Widget ,下段代码将展示右侧的 编写,左侧雷同。
/// 右侧的 Tab Bar
Widget _myTabBarRight(BuildContext context,bool isRight){
return InkWell(
onTap: (){
Provide.value<DetailsInfoProvide>(context).changeLeftAndRight('right');
},
child: Container(
padding:EdgeInsets.all(10.0),
alignment: Alignment.center,
width: ScreenUtil().setWidth(375),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
width: 1.0,
color: isRight?Colors.pink:Colors.black12
)
)
),
child: Text(
'评论',
style: TextStyle(
color:isRight?Colors.pink:Colors.black
),
),
),
);
}
通过 Provide 来控制两个tab 的状态。接下来我们使用 一个可以通过 html代码本文展示 Html 界面的 第三方库: ‘flutter_html’,使用范例:
return Container(
child: Html(
// goodsDetail 为网页代码字符串
data:goodsDetail
),
);
至于最后的 我的界面 这里就一笔略过了… ,最后说一下 dio 的使用 代码:
/// 公用 post dio请求方法
/// 参数使用{}包裹,表示该参数可以不需要传。
Future requestPost(url,{formData})async{
try{
Response response;
Dio dio = new Dio();
dio.options.contentType="application/x-www-form-urlencoded";
if(formData==null){
response = await dio.post(servicePath[url]);
}else{
response = await dio.post(servicePath[url],data:formData);
}
if(response.statusCode==200){
return response.data;
}else{
throw Exception('后端接口出现异常,请检测代码和服务器情况.........');
}
}catch(e){
return print('ERROR:======>$e');
}
}
针对两个月以来 利用空闲时间 编写的 Flutter 简单商城Demo,自我认为在有Java 和 kotlin 的基础上 还是比较简单好学的,学习的比较多的 就是Flutter 中的各种各样的 Widget使用 及其方法,还有第三方库 (Provide dio 的使用),总结比较简单,暂时就写到这里。 魔都大白(●—●)… bye