Flutter实战视频-移动电商-31.列表页_列表切换交互制作
31.列表页_列表切换交互制作
博客地址:https://jspang.com/post/FlutterShop.html#toc-c42
点击左侧的大类右边的小类也跟着变化
新建provide
要改变哪里就建哪里的provide,我们现在要改变的是右边的商品列表的数组。
category_goods_list.dart
这样我们的provide类就做好了
做好的provide类放到main.dart中注册
这一步叫做 把状态放入顶层
category_page.dart修改
_getGoodsList方法整体移动到左侧的大类
我们把他移动到了这里
方法移动过来以后,我们要接受一个参数类别id,这个类别是可选的,可选的参数用{}括起来
再判断传入的参数是否有值,如果有值就用这个值,如果没有值就用默认的白酒的分类是4
引入provide更改右侧的列表数据
import '../provide/category_goods_list.dart';
这个时候我们会发现我们传入list的值有错。
实际上我们的CategoryGoodsListModel类里面的data才是我们要传入的列表值 List<CategoryListData>
所以这里我们要用.data的形式
修改我们的右侧列表类
list没有用,已经换成了provide的状态管理。这里删除掉就可以了。
我们要在container的外层包括一层provide才可以去使用状态管理。
外层包括Provide,builder里面三个参数,1:上下文对象 2:child 3:就是我们的数据了
所有list的地方都要换成newList
使用我们改编自状态的方法:_getGoodsList
在我们左侧大类的onTap事件里面去调用这个小类数据的方法
展示效果
点击后右侧出现了数据
刚进入页面的时候调用一次加载右侧列表的数据
默认记载白酒的子类数据
最终代码
lib/provide/category_goods_list.dart
import 'package:flutter/material.dart'; import '../model/categoryGoodsList.dart'; class CategoryGoodsListProvide with ChangeNotifier{ List<CategoryListData> goodsList=[]; //点击大类时候更换商品列表 getGoodsList(List<CategoryListData> list){ goodsList=list; notifyListeners(); } }
main.dart
import 'package:flutter/material.dart'; import './pages/index_page.dart'; import 'package:provide/provide.dart'; import './provide/counter.dart'; import './provide/child_category.dart'; import './provide/category_goods_list.dart'; void main(){ var counter=Counter(); var childCategory=ChildCategory(); var categoryGoodsListProvide=CategoryGoodsListProvide(); var providers=Providers(); //注册 依赖 providers ..provide(Provider<Counter>.value(counter)) ..provide(Provider<CategoryGoodsListProvide>.value(categoryGoodsListProvide)) ..provide(Provider<ChildCategory>.value(childCategory)); runApp(ProviderNode(child: MyApp(),providers: providers,)); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child:MaterialApp( title:'百姓生活+', debugShowCheckedModeBanner: false, theme: ThemeData( primaryColor: Colors.pink ), home: IndexPage(), ) ); } }
import 'package:flutter/material.dart'; import '../service/service_method.dart'; import 'dart:convert'; import '../model/category.dart'; import '../model/categoryGoodsList.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provide/provide.dart'; import '../provide/child_category.dart'; import '../provide/category_goods_list.dart'; class CategoryPage extends StatefulWidget { @override _CategoryPageState createState() => _CategoryPageState(); } class _CategoryPageState extends State<CategoryPage> { @override Widget build(BuildContext context) { //_getCategory(); return Scaffold( appBar: AppBar(title: Text('商品分类'),), body: Container( child: Row( children: <Widget>[ LeftCategoryNav(), Column( children: <Widget>[ RightCategoryNav(), CategoryGoodsList() ], ) ], ), ), ); } } //左侧大类导航 class LeftCategoryNav extends StatefulWidget { @override _LeftCategoryNavState createState() => _LeftCategoryNavState(); } class _LeftCategoryNavState extends State<LeftCategoryNav> { List list=[]; var listIndex=0; @override void initState() { super.initState(); _getCategory();//请求接口的数据 _getGoodsList();//参数是可选的默认是4 所以这里可以不用传值 } @override Widget build(BuildContext context) { return Container( width: ScreenUtil().setWidth(180), decoration: BoxDecoration( border: Border( right: BorderSide(width:1.0,color: Colors.black12),//有边框 ) ), child: ListView.builder( itemCount: list.length, itemBuilder: (contex,index){ return _leftInkWell(index); }, ), ); } Widget _leftInkWell(int index){ bool isClick=false; isClick=(index==listIndex)?true:false; return InkWell( onTap: (){ setState(() { listIndex=index; }); var childList=list[index].bxMallSubDto;//当前大类的子类的列表 var categoryId=list[index].mallCategoryId;//大类的id Provide.value<ChildCategory>(context).getChildCategory(childList); _getGoodsList(categoryId:categoryId); }, child: Container( height: ScreenUtil().setHeight(100), padding: EdgeInsets.only(left:10.0,top:10.0), decoration: BoxDecoration( color: isClick?Color.fromRGBO(236, 236, 236, 1.0): Colors.white, border: Border( bottom: BorderSide(width: 1.0,color: Colors.black12) ) ), child: Text( list[index].mallCategoryName, style: TextStyle(fontSize: ScreenUtil().setSp(28)),//设置字体大小,为了兼容使用setSp ), ), ); } void _getCategory() async{ await request('getCategory').then((val){ var data=json.decode(val.toString()); //print(data); CategoryModel category= CategoryModel.fromJson(data); setState(() { list=category.data; }); Provide.value<ChildCategory>(context).getChildCategory(list[0].bxMallSubDto); }); } void _getGoodsList({String categoryId}) async { var data={ 'categoryId':categoryId==null?'4':categoryId,//白酒的默认类别 'CategorySubId':"", 'page':1 }; await request('getMallGoods',formData: data).then((val){ var data=json.decode(val.toString()); CategoryGoodsListModel goodsList=CategoryGoodsListModel.fromJson(data);//这样就从json'转换成了model类 //print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>:${goodsList.data[0].goodsName}'); // setState(() { // list=goodsList.data; // }); Provide.value<CategoryGoodsListProvide>(context).getGoodsList(goodsList.data); }); } } class RightCategoryNav extends StatefulWidget { @override _RightCategoryNavState createState() => _RightCategoryNavState(); } class _RightCategoryNavState extends State<RightCategoryNav> { //List list = ['名酒','宝丰','北京二锅头','舍得','五粮液','茅台','散白']; @override Widget build(BuildContext context) { return Provide<ChildCategory>( builder: (context,child,childCategory){ return Container( height: ScreenUtil().setHeight(80), width: ScreenUtil().setWidth(570),//总的宽度是750 -180 decoration: BoxDecoration( color: Colors.white,//白色背景 border: Border( bottom: BorderSide(width: 1.0,color: Colors.black12)//边界线 ) ), child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: childCategory.childCategoryList.length, itemBuilder: (context,index){ return _rightInkWell(childCategory.childCategoryList[index]); }, ), ); } ); } Widget _rightInkWell(BxMallSubDto item){ return InkWell( onTap: (){},//事件留空 child: Container(//什么都加一个container,这样好布局 padding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),//上下是10 左右是5.0 child: Text( item.mallSubName, style:TextStyle(fontSize: ScreenUtil().setSp(28)), ), ), ); } } //商品列表 ,可以上拉加载 class CategoryGoodsList extends StatefulWidget { @override _CategoryGoodsListState createState() => _CategoryGoodsListState(); } class _CategoryGoodsListState extends State<CategoryGoodsList> { @override void initState() { //_getGoodsList(); super.initState(); } @override Widget build(BuildContext context) { return Provide<CategoryGoodsListProvide>( builder: (context,child,data){ return Container( width: ScreenUtil().setWidth(570), height: ScreenUtil().setHeight(974), child: ListView.builder( itemCount: data.goodsList.length, itemBuilder: (contex,index){ return _listWidget(data.goodsList,index); }, ), ); }, ); } Widget _goodsImage(List newList,index){ return Container( width: ScreenUtil().setWidth(200),//设置200的宽度 限制 child: Image.network(newList[index].image), ); } Widget _goodsName(List newList,index){ return Container( padding: EdgeInsets.all(5.0),//上下左右都是5.0的内边距 width: ScreenUtil().setWidth(370),//370是一个大约的值 child: Text( newList[index].goodsName, maxLines: 2,//最多显示2行内容 overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: ScreenUtil().setSp(28)),//字体大小 ), ); } Widget _goodsPrice(List newList,index){ return Container( margin: EdgeInsets.only(top:20.0),//和上面的外间距 width: ScreenUtil().setWidth(370),//370是一个大约的值 child: Row( children: <Widget>[ Text( '价格¥${newList[index].presentPrice}', style: TextStyle(color: Colors.pink,fontSize: ScreenUtil().setSp(30)), ), Text( '价格¥${newList[index].oriPrice}', style: TextStyle( color: Colors.black26, decoration: TextDecoration.lineThrough ),//删除线的样式 ) ], ), ); } Widget _listWidget(List newList,int index){ return InkWell( onTap: (){}, child: Container( padding: EdgeInsets.only(top:5.0,bottom:5.0), decoration: BoxDecoration( color: Colors.white, border: Border( bottom: BorderSide(width: 1.0,color: Colors.black12) ) ), child: Row( children: <Widget>[ _goodsImage(newList,index), Column( children: <Widget>[ _goodsName(newList,index), _goodsPrice(newList,index) ], ) ], ), ), ); } }