Flower_gift 簡單的Flutter實戰app(四)

0001.jpg
項目git地址:flower_gift
tabBar-分類界面:

效果:


11324.gif
頭部搜索欄的搭建:
//頂部搜索框;
  Widget _buildSearchBar(){
    return Container(
              margin: EdgeInsets.symmetric(horizontal: 10.0,vertical: 8.0),
              decoration: BoxDecoration(
                 color: Colors.black12,
                 borderRadius: BorderRadius.all(Radius.circular(22.0)),
              ),
              child: Row(
                 crossAxisAlignment: CrossAxisAlignment.start,
                 children: <Widget>[
                    Expanded(
                      flex: 1,
                      child: Container(
                        padding: EdgeInsets.symmetric(horizontal: 8.0),
                        child: TextFormField(
                            decoration: InputDecoration(
                                border: InputBorder.none,
                                hintText: "請輸入關鍵字",
                                hintStyle: TextStyle(
                                  color: Colors.black
                                ),
                                icon: Icon(Icons.search,color:Colors.black)
                            ),
                          ),
                      ) 
                      
                    ),
                    
                 ],
              ),
    );
  }

使用:

 return Scaffold(
        appBar: AppBar(
           backgroundColor: Colors.white,
           title: _buildSearchBar()
        ),
        body: ...

這里就是說,開始我以為這個Scaffold的title屬性只能是這個Text組件控制這個導航欄title.原來這個也是完全可以自定義的。

body布局部分:
 body: FutureBuilder(
            future: _getCategoryPage(context),
            builder: (context,snapshot){
              if(snapshot.hasData){
                return Container(
                    color: Colors.white,
                    child: Row(
                        children: <Widget>[
                          Expanded(
                            flex: 2,
                            child: CategoryLeftNav()
                          ),
                          Expanded(
                            flex: 5,
                            child: CategoryRightCategory()
                          )
                        ],
                      ),  
                );  
              }else{
                return Center(
                  child: Text("暫無數據"),
                );
              }
            },
        ),


 
  //網絡請求
   Future _getCategoryPage(BuildContext context) async{
     await Provide.value<CategoryPageProvide>(context).getCategoryPageData();
     return "完成加載....";
  }

整體布局我把這個作為左右兩部分吧,所以這個就直接用Row,然后里面嵌套這個Expanded組件,用flex來控制所占寬度比。

左邊導航欄
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../model/categoryPage_model_entity.dart';
import 'package:provide/provide.dart';
import '../../provide/categoryPage_provide.dart';

class CategoryLeftNav extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return Provide<CategoryPageProvide>(
        builder: (context,child,val){
          var categoryPageModelEntity = val.categoryModelEntity;
          return  Container(
            decoration: BoxDecoration(
              border: Border(
                right: BorderSide(
                    color: Colors.black12,
                    width: 1.0,
                    style: BorderStyle.solid
                )
              )
            ),
            child: ListView.builder(
              itemCount: categoryPageModelEntity.categorys.length,
              itemBuilder:(context,index){
                  return Container(
                      color: Colors.white,
                      child: InkWell(
                          //設置點擊閃爍那一下的文字顏色
                          splashColor: Colors.redAccent.withOpacity(0.5),
                          onTap: (){
                             Provide.value<CategoryPageProvide>(context).switchCategory(index);
                          },
                          child: Column(
                            children: <Widget>[
                              SizedBox(height: 15.0,),
                                Container(
                                  alignment: Alignment.center,
                                  padding: const EdgeInsets.symmetric(vertical: 4.0),
                                  decoration: (Provide.value<CategoryPageProvide>(context).currentIndex == index) ?  BoxDecoration(
                                      border: Border(
                                          left: BorderSide(
                                            color: Colors.orange,
                                            width: 3.0,
                                            style: BorderStyle.solid
                                          )
                                      )
                                    ) : null,
                                    child: Text(
                                        categoryPageModelEntity.categorys[index].type,
                                        style: TextStyle(fontSize: 18.0),
                                      ),
                              ),
                              SizedBox(height: 15.0,),
                              
                            ],
                          ) 
                        
                          
                      )
                      
                  );
              },
            ),
            
        );
      }
   );
  }
}

這個布局就比較簡單的,主要就是利用Provide來管理了當前點擊的分類項,然后左邊的指示條我就直接用的這個邊框來做的。

右邊分類布局部分:
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../model/categoryPage_model_entity.dart';
import 'package:provide/provide.dart';
import '../../provide/categoryPage_provide.dart';

class CategoryRightCategory extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provide<CategoryPageProvide>(
        builder: (context,child,val){
           var currentIndex = Provide.value<CategoryPageProvide>(context).currentIndex;
           var categoryModelCategory = val.categoryModelEntity.categorys[currentIndex];
           var categoryBanners = categoryModelCategory.categoryBanner;
           var areasItem = categoryModelCategory.areas[0];//默認只做第一排的商品分類詳情了
           var head = areasItem.head;//看看是否有頭部標題欄
           var contents = areasItem.contents;
           return Container(
              child:ListView(
                
                   children: <Widget>[
                      _buildTopBanner(context, categoryModelCategory.banner),
                    (categoryBanners != null) ? _buildCategoryBanner(context, categoryBanners) : SizedBox(height: 1.0,),
                    (head != null) ? _buildTitle(head) : SizedBox(height: 1.0,),
                    Divider(),
                    _buildCategoryShow(context, contents),
                   ],
                 
              )
             
           );
        },
    );
    
  }

  //頂部banner
  Widget _buildTopBanner(BuildContext context,CategoryModelCategorysBanner banner){
      return Padding(
         padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
         child: Container(
            height: MediaQuery.of(context).size.height / 7,
            child: Image.network(banner.imageUrl,fit:BoxFit.fill,),
         ), 
      );
   }

   //分類banner -- 需要判斷顯示否
   Widget _buildCategoryBanner(BuildContext context,List<CategoryModelCategorysCategorybanner> categoryBanners){
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0),
        child: Container(
           height: MediaQuery.of(context).size.height / 7,
           child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: _categoryBanners(context, categoryBanners)
           ),
        ),
      );
   }
   List<Widget> _categoryBanners(BuildContext context, List<CategoryModelCategorysCategorybanner> categoryBanners){
       List<Widget> list = new List();
        for(var i = 0; i < categoryBanners.length; i++){
          list.add(
              Container(
                width: (MediaQuery.of(context).size.width / 7 * 5  - 40.0)/3,
                child: Image.network(categoryBanners[i].imageUrl,fit:BoxFit.fill),
              )
              
          ); 
     }
     return list;
   }
 
   //標題欄
   Widget _buildTitle(dynamic head){
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0,vertical: 5.0),
        child: Row(
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
           children: <Widget>[
              Text(head["Title"]),
              Text(head["UrlDesc"])
           ],
        ),
      );

   }
  //分類展示
   Widget _buildCategoryShow(BuildContext context,List<CategoryModelCategorysAreasContent> contents){
     return Padding(
            padding: const EdgeInsets.symmetric(horizontal: 10.0),
            child: Wrap(
               alignment: WrapAlignment.spaceBetween,
               children: _categoryShow(context, contents)
            ),
        
     );
     
   }
   //分類展示遍歷
   List<Widget> _categoryShow(BuildContext context,List<CategoryModelCategorysAreasContent> contents){
       List<Widget> list = new List();
        for(var i = 0; i < contents.length; i++){
          list.add(
              Container(
                //  height:  MediaQuery.of(context).size.height / 7 + 20.0,
                 width:  (MediaQuery.of(context).size.width / 7 * 5 - 30.0)/3,
                 child: Column(
                     mainAxisAlignment: MainAxisAlignment.center,
                     children: <Widget>[
                        SizedBox(height:25.0),
                       (contents[i].text != null) ? CircleAvatar(
                           child: Image.network(contents[i].imageUrl),
                        ) : Padding(
                           padding: const EdgeInsets.symmetric(horizontal: 5.0),
                           child:Image.network(contents[i].imageUrl),
                        ),
                        SizedBox(height: 15.0,),
                        (contents[i].text != null) ? Text(
                          contents[i].text
                        ) : SizedBox(height: 1.0,),
                         
                     ],

                 ),
              )
              
          ); 
     }
     return list;
   }
}

這邊布局也是比較簡單的,主要就是考慮這個數據是否為null,來確定顯示哪一部分。

結尾:這個頁面的分類項點擊的邏輯還沒做,這個路由的配置就利用首頁來做就好了,具體的分類列表項布局還算簡單,就是其中的邏輯比較雜。其次這個搜索邏輯也沒有做,看后面有時間補上。商品詳情頁
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容