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('我的'))
          ],
        ),
      ),
    );
  }
}

 

posted @ 2019-09-02 22:13  生如逆旅,一苇以航  阅读(3170)  评论(0编辑  收藏  举报