16 Flutter仿京东商城项目 跳转到搜索页面实现搜索功能 以及搜索筛选
ProductList.dart
import 'package:flutter/material.dart'; import '../services/ScreenAdaper.dart'; import '../config/Config.dart'; import 'package:dio/dio.dart'; import '../model/ProductModel.dart'; import '../widget/LoadingWidget.dart'; class ProductListPage extends StatefulWidget { Map arguments; ProductListPage({Key key, this.arguments}) : super(key: key); _ProductListPageState createState() => _ProductListPageState(); } class _ProductListPageState extends State<ProductListPage> { //通过事件打开侧边栏,需要全局声明一下: final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); //配置下拉加载更多: ScrollController _scrollController = ScrollController(); //分页: int _page = 1; //每一页有多少条数据: int _pageSize = 10; //分页: List _productList = []; //排序: String _sort = ""; //解决重复请求的问题: bool flag = true; //是否有数据: bool _hasMore = true; //是否有搜索的数据: bool _hasData = true; // 一级导航数据 /* 价格升序:sort=price_1 价格降序:sort=price_-1 销量升序:sort=salecount_1 销量降序:sort=salecount_-1 */ List _subHeaderList = [ {"id": 1, "title": "综合", "fileds": 'all', "sort": -1}, {"id": 2, "title": "销量", "fileds": 'salecount', "sort": -1}, {"id": 3, "title": "价格", "fileds": 'price', "sort": -1}, {"id": 4, "title": "筛选"}, ]; int _selectHeaderId = 1; //配置search搜索框的值: var _initKeywordsController = new TextEditingController(); //cid var _cid; var _keywords; //初始化的时候获取的生命周期函数: @override void initState() { super.initState(); this._cid = widget.arguments["cid"]; this._keywords = widget.arguments["keywords"]; //给search框框赋值: this._initKeywordsController.text = this._keywords; widget.arguments['keywords'] == null ? this._initKeywordsController.text = "" : this._initKeywordsController.text = widget.arguments['keywords']; _getProductListData(); //监听滚动条滚动事件: _scrollController.addListener(() { // _scrollController.position.pixels //获取滚动条滚动高度 // _scrollController.position.maxScrollExtent //获取页面滚动高度: if (_scrollController.position.pixels > _scrollController.position.maxScrollExtent - 20) { if (this.flag && this._hasMore) { _getProductListData(); } } }); } //获取商品列表的数据: _getProductListData() async { setState(() { this.flag = false; }); var api; print(widget.arguments['keywords']); if (this._keywords == null) { api = '${Config.domain}api/plist?cid=${this._cid}&page=${_page}&sort=${this._sort}&pageSize=${_pageSize}'; } else { api = '${Config.domain}api/plist?search=${this._keywords}&page=${_page}&sort=${this._sort}&pageSize=${_pageSize}'; } var result = await Dio().get(api); var productList = ProductModel.fromJson(result.data); print(productList.result); if (productList.result.length < this._pageSize) { setState(() { this._productList.addAll(productList.result); this._hasMore = false; this.flag = true; // this._productList = productList.result; }); } else { setState(() { this._productList.addAll(productList.result); this._page++; this.flag = true; // this._productList = productList.result; }); } //判断是否有搜索的数据: if (productList.result.length == 0) { setState(() { this._hasData = false; }); } else { setState(() { this._hasData = true; }); } } //显示加载中的圈圈: Widget _showMore(index) { if (this._hasMore) { return (index == this._productList.length - 1) ? LoadingWidget() : Text(''); } else { return (index == this._productList.length - 1) ? Text("---暂无其他数据了--") : Text(''); } } //商品列表: Widget _productListWidget() { if (this._productList.length > 0) { return Container( padding: EdgeInsets.all(10), margin: EdgeInsets.only(top: ScreenAdaper.height(80)), child: ListView.builder( controller: _scrollController, itemBuilder: (context, index) { //处理图片: String pic = this._productList[index].pic; pic = Config.domain + pic.replaceAll('\\', '/'); //获得每一个元素: return Column( children: <Widget>[ Row( children: <Widget>[ Container( width: ScreenAdaper.width(180), height: ScreenAdaper.height(180), child: Image.network("${pic}", fit: BoxFit.cover), ), Expanded( flex: 1, child: Container( height: ScreenAdaper.height(180), margin: EdgeInsets.only(left: 10), // color: Colors.red, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( "${this._productList[index].title}", maxLines: 2, overflow: TextOverflow.ellipsis, ), Row( children: <Widget>[ Container( height: ScreenAdaper.height(36), margin: EdgeInsets.only(right: 10), padding: EdgeInsets.fromLTRB(10, 0, 10, 0), //注意:如果Container里面加上decoration属性,这个时候color属性必须放到BoxDecoration decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), // color:Color.fromRGBO(230, 230, 230, 0.9) ), child: Text('4G'), ), Container( height: ScreenAdaper.height(36), margin: EdgeInsets.only(right: 10), padding: EdgeInsets.fromLTRB(10, 0, 10, 0), //注意:如果Container里面加上decoration属性,这个时候color属性必须放到BoxDecoration decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), // color:Color.fromRGBO(230, 230, 230, 0.3) ), child: Text('16G'), ) ], ), Text("¥ ${this._productList[index].price}", style: TextStyle(color: Colors.red, fontSize: 16)) ], ), ), ) ], ), Divider( height: 20, ), this._showMore(index) ], ); }, itemCount: this._productList.length, ), ); } else { return LoadingWidget(); } } //导航改变的时候触发: _subHeaderChange(id) { if (id == 4) { _scaffoldKey.currentState.openEndDrawer(); } setState(() { this._selectHeaderId = id; this._sort = "${this._subHeaderList[id - 1]['fileds']}_${this._subHeaderList[id - 1]['sort']}"; //重置分页: this._page = 1; //重置数据: this._productList = []; this._subHeaderList[id - 1]['sort'] = this._subHeaderList[id - 1]['sort'] * -1; //回到顶部: _scrollController.jumpTo(0); //重置_hasMore this._hasMore = true; //重新请求数据: this._getProductListData(); }); } //显示Header icon Widget _showIcon(id) { if (id == 2 || id == 3) { if (this._subHeaderList[id - 1]['sort'] == 1) { return Icon(Icons.arrow_drop_down); } return Icon(Icons.arrow_drop_up); } return Text(''); } //筛选导航: Widget _subHeaderWidget() { return Positioned( top: 0, height: ScreenAdaper.height(80), width: ScreenAdaper.width(750), child: Container( height: ScreenAdaper.height(80), width: ScreenAdaper.width(750), // color: Colors.red, decoration: BoxDecoration( border: Border( bottom: BorderSide( width: 1, color: Color.fromRGBO(233, 233, 233, 0.9)))), child: Row( children: this._subHeaderList.map((value) { return Expanded( flex: 1, child: InkWell( child: Padding( padding: EdgeInsets.fromLTRB( 0, ScreenAdaper.height(20), 0, ScreenAdaper.height(20)), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( "${value['title']}", textAlign: TextAlign.center, style: TextStyle( color: (this._selectHeaderId == value["id"]) ? Colors.red : Colors.black), ), _showIcon(value['id']) ], ), ), onTap: () { _subHeaderChange(value["id"]); }, ), ); }).toList()), ), ); } @override Widget build(BuildContext context) { ScreenAdaper.init(context); return Scaffold( key: _scaffoldKey, appBar: AppBar( title: Container( child: TextField( controller: this._initKeywordsController, autofocus: false, decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide.none)), onChanged: (value) { setState(() { this._keywords = value; }); }, ), height: ScreenAdaper.height(68), decoration: BoxDecoration(color: Color.fromRGBO(233, 233, 233, 0.8)), ), actions: <Widget>[ InkWell( child: Container( height: ScreenAdaper.height(68), width: ScreenAdaper.width(80), child: Row( children: <Widget>[Text('搜索')], ), ), onTap: () { this._subHeaderChange(1); }, ) ], ), endDrawer: Drawer( child: Container( child: Text('实现筛选功能'), ), ), // body: Text("${widget.arguments}"), body:_hasData?Stack( children: <Widget>[_productListWidget(), _subHeaderWidget()], ):Center( child: Text('没有您要浏览的数据') ), ); } }
Search.dart
import 'package:flutter/material.dart'; import 'package:flutter_jdshop/services/ScreenAdaper.dart'; class SearchPage extends StatefulWidget { SearchPage({Key key}) : super(key: key); _SearchPageState createState() => _SearchPageState(); } class _SearchPageState extends State<SearchPage> { var _keywords; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Container( child: TextField( autofocus: true, decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide.none)), onChanged: (value){ this._keywords=value; }, ), height: ScreenAdaper.height(68), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.8), borderRadius: BorderRadius.circular(30)), ), actions: <Widget>[ InkWell( child: Container( height: ScreenAdaper.height(68), width: ScreenAdaper.width(80), child: Row( children: <Widget>[Text('搜索')], ), ), onTap: () { print(896); Navigator.pushReplacementNamed(context,'/productList',arguments: { "keywords":this._keywords }); }, ) ], ), body: Container( padding: EdgeInsets.all(10), child: ListView( children: <Widget>[ Container( child: Text('热搜', style: Theme.of(context).textTheme.title), ), Divider(), Wrap( children: <Widget>[ Container( padding: EdgeInsets.all(10), margin: EdgeInsets.all(10), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(10)), child: Text('女装'), ), Container( padding: EdgeInsets.all(10), margin: EdgeInsets.all(10), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(10)), child: Text('女装'), ), Container( padding: EdgeInsets.all(10), margin: EdgeInsets.all(10), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(10)), child: Text('女装'), ), Container( padding: EdgeInsets.all(10), margin: EdgeInsets.all(10), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(10)), child: Text('女装'), ), Container( padding: EdgeInsets.all(10), margin: EdgeInsets.all(10), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(10)), child: Text('女装'), ) ], ), SizedBox(height: 10), Container( child: Text('历史记录', style: Theme.of(context).textTheme.title), ), Divider(), Column( children: <Widget>[ ListTile( title: Text('女装'), ), Divider(), ListTile( title: Text('女装'), ), Divider(), ListTile( title: Text('女装'), ), Divider(), ListTile( title: Text('女装'), ), Divider(), ], ), SizedBox(height: 100), InkWell( onTap: (){ }, child: Container( width: ScreenAdaper.width(400), height: ScreenAdaper.height(64), decoration: BoxDecoration( border: Border.all(color: Colors.black54, width: 1)), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[Icon(Icons.delete), Text('清空历史记录')], ), ), ) ], ), )); } }
router.dart
import 'package:flutter/material.dart'; import '../pages/tabs/Tabs.dart'; import '../pages/Search.dart'; import '../pages/ProductList.dart'; //配置路由的地方: final routes = { '/': (context) => Tabs(), '/search': (context) => SearchPage(), '/productList': (context,{arguments}) => ProductListPage(arguments:arguments), }; //固定写法: var onGenerateRoute = (RouteSettings settings) { // 统一处理 final String name = settings.name; final Function pageContentBuilder = routes[name]; if (pageContentBuilder != null) { if (settings.arguments != null) { final Route route = MaterialPageRoute( builder: (context) => pageContentBuilder(context, arguments: settings.arguments)); return route; } else { final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context)); return route; } } };
Tabs.dart
import 'package:flutter/material.dart'; import '../../services/ScreenAdaper.dart'; import 'Home.dart'; import 'Cart.dart'; import 'Category.dart'; import 'User.dart'; class Tabs extends StatefulWidget { Tabs({Key key}) : super(key: key); _TabsState createState() => _TabsState(); } class _TabsState extends State<Tabs> { int _currentIndex = 1; PageController _pageController; void initState() { super.initState(); this._pageController = new PageController(initialPage: this._currentIndex); } List<Widget> _pageList = [HomePage(), CategoryPage(), CartPage(), UserPage()]; @override Widget build(BuildContext context) { ScreenAdaper.init(context); return Container( child: Scaffold( appBar:_currentIndex!=3?AppBar( leading: IconButton( icon: Icon(Icons.center_focus_weak, size: 28, color: Colors.black87), onPressed: null, ), title:InkWell( child: Container( height: ScreenAdaper.height(56), decoration: BoxDecoration( color: Color.fromRGBO(233,233,233, 0.8), borderRadius: BorderRadius.circular(30) ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Icon(Icons.search), Text('笔记本',style:TextStyle( fontSize: ScreenAdaper.size(28) )) ], ), ), onTap: (){ Navigator.pushNamed(context,'/search'); }, ), actions: <Widget>[ IconButton( icon: Icon(Icons.message, size: 28, color: Colors.black87), onPressed: null, ) ], ):AppBar( title: Text('用户中心'), ), //页面状态保持第一种方法: //保持所有的页面状态,使用indexedStack // body:IndexedStack( // index: this._currentIndex, // children:_pageList // ), //保持部分页面的状态: // body: PageView( //修改的部分: controller: this._pageController, children: this._pageList, onPageChanged:(index){ setState(() { this._currentIndex=index; }); }, // physics: NeverScrollableScrollPhysics(), //禁止pageView滑动 ), bottomNavigationBar: BottomNavigationBar( currentIndex: this._currentIndex, onTap: (index) { this.setState(() { this._currentIndex = index; this._pageController.jumpToPage(this._currentIndex); }); }, type: BottomNavigationBarType.fixed, fixedColor: Colors.red, items: [ BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')), BottomNavigationBarItem( icon: Icon(Icons.category), title: Text('分类')), BottomNavigationBarItem( icon: Icon(Icons.shopping_cart), title: Text('购物车')), BottomNavigationBarItem(icon: Icon(Icons.people), title: Text('我的')) ], ), ), ); } }