Flower_gift 简单的Flutter实战app(五)

ed94bbb1f573dd5dcd00505fab7cfb72.png

商品详情页完成--看看效果:

1111.gif

商品详情页布局

商品详情页一般都是这个商城app中布局最多的一个界面,也是各种交互比较多的界面,整整写了一天才写完(其实还没完,后面有些无关紧要的图片就没有写了)
还是一点来吧

首先是路由配置和数据获取

路由配置:

Handler detailsHandler = Handler(
   handlerFunc: (BuildContext context,Map<String,List<String>> params){
      String itemCode = params["itemCode"].first;//传递请求参数
      print("传递的itemCode是: ${itemCode}");
      return DetailsPage(itemCode);
   }

 static String detailsPage = "/detailsPage";
 router.define(detailsPage,handler: detailsHandler);

//使用:
onTap: (){
          Application.router.navigateTo(context, "/detailsPage?itemCode=${sectionListItem.productCode}");
       },
     

数据获取:

import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../provide/details_provide.dart';
import './detailsSubWidget/top_swiper_widget.dart';
import './detailsSubWidget/detailsBottom_widget.dart';
import './detailsSubWidget/detailsTitle_widget.dart';
import './detailsSubWidget/detailsDescribe_widget.dart';
import './detailsSubWidget/detailsDelivery_widget.dart';
import './detailsSubWidget/detailsEvaluate_widget.dart';
import './detailsSubWidget/detailsCompany_widget.dart';
import './detailsSubWidget/detailsImgText_widget.dart';

class DetailsPage extends StatelessWidget {
  String itemCode;
  DetailsPage(this.itemCode);
  
  

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      
      appBar: AppBar(
          backgroundColor: Colors.white,
          leading: IconButton(
            icon: Icon(Icons.arrow_back,color: Colors.black,),
            onPressed: (){
                Navigator.pop(context);
            },
          ),
          title: Provide<DetailsPageProvide>(
              builder: (context,child,val){

                 return Text(val.datas.itemName,
                   style: TextStyle(color:Colors.black),
                 );
              },
          )
          
      ),
      body: FutureBuilder(
              future: _getDetailPage(context),
              builder: (context,snapshot){
                if(snapshot.hasData){
                  return Stack(
                       children: <Widget>[
                          Container(
                            color: Colors.black12,
                            child: ListView(
                                children: <Widget>[
                                  TopSwiper(),
                                  DetailsTitle(),
                                  SizedBox(height: 8.0,),
                                  DetailsDescribe(),
                                  SizedBox(height: 8.0,),
                                  DetailsDelivery(),
                                  SizedBox(height: 8.0,),
                                  DetailsEvaluate(),
                                  SizedBox(height: 8.0,),
                                  DetailsCompany(),
                                  SizedBox(height: 8.0,),
                                  DetailsImgText(),
                                  SizedBox(height: 80.0,)
                               ],
                            ),
                          ),
                          Positioned(
                             bottom: 0,
                             left: 0,
                             child: DetailsBottom(),
                          )
  
                       ],
                  );
                   
                }else{
                    return Center(
                      child: Text("暂无数据"),
                    ); 
                }
          }
      )
    );
  }

  Future _getDetailPage(BuildContext context) async{
      await Provide.value<DetailsPageProvide>(context).getDetailsPageData(itemCode);
      return "加载完成";
  }

}

从ListView中就是我拆分的详情页部分的各个组件。下面还是将各个组件中的代码贴出来。

顶部图片轮播
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import 'package:flutter_swiper/flutter_swiper.dart';



class TopSwiper extends StatelessWidget {
  

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
         builder: (context,child,val){
            var coverImages = val.datas.coverImages;
            return Container(
                  color: Colors.white,
                  height: MediaQuery.of(context).size.height*0.6,
                  child: Swiper(
                    itemBuilder: (BuildContext context,int index){
                        return Image.network("${coverImages[index]}");
                    },
                    onTap: (index){
                        print("点击了轮播组件:${index}");
                    },
                    itemCount: coverImages.length,
                    pagination: buildSwiperPagintion(),
                    autoplay: true,
                    
                  ),
                );
         },
    );
  }

  buildSwiperPagintion(){
     return SwiperPagination(
        builder: FractionPaginationBuilder(
           color: Colors.white,
           activeColor: Colors.orange
        )
     );
  }
}

这个轮播插件还是挺好用的,就是这个Page指示器和app上的不一样,由于这个插件只提供了两种样式,如果想要和app中的一样需要自定义这个SwiperPagination, 后面完成后,来试试自己自定义这个东东。

顶部标题和价格
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';

class DetailsTitle extends StatelessWidget {
    

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
          builder: (context,child,val){
             var datas = val.datas;
             return Container(
               
               decoration: BoxDecoration(
                 color: Colors.white,
                  border: Border(
                     top: BorderSide(width: 1,color: Colors.black12),
                     bottom: BorderSide(width: 1,color:Colors.black12)
                  )
               ), 
               child: Padding(
                    padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
                    child: Container(
                        child: Column(
                          children: <Widget>[
                            _buildTitle(datas.itemName,datas.introduction),
                            SizedBox(height: 15.0,),
                            _buildPrice(datas),

                          ],
                        ),
                    ), 
                  ),
             );
             
          },
    );
    
  }

  //标题
  Widget _buildTitle(String name,String introduction){
     return Container(
         
         child: Row(
            children: <Widget>[
               Expanded(
                 flex: 8,
                 child: Container(
                    child: Text(
                       "${name}--${introduction}",
                       maxLines: 1,
                       overflow: TextOverflow.ellipsis,
                    ),
                 ),
               ),
               Expanded(
                 flex: 2,
                 child: Container(
                    alignment: Alignment.centerRight,
                    child:Icon(Icons.star_border),
                 )
                 
               )
            ],
         ),
     );
  }
  //价格
  Widget _buildPrice(DetailsModelDatas datas){
     return Container(
       child: Row(
         mainAxisAlignment: MainAxisAlignment.spaceBetween,
         children: <Widget>[
            Row(
              children: <Widget>[
                 Text(
                   "¥${datas.price}",
                   style: TextStyle(
                      color:Colors.orangeAccent,
                      fontSize: 24.0
                   ), 
                 ),
                 SizedBox(width: 5.0,),
                 Text(
                   "¥${datas.linePrice}",
                   style: TextStyle(
                     color: Colors.black26,
                     decoration: TextDecoration.lineThrough
                   ),
                 )
              ],
            ),
            Container(
               alignment: Alignment.centerRight,
               child: Text(datas.sale),
            )

         ],
       ), 
     );
  }
}

这个没什么好说的,说说这个Icon吧,这里有这个flutter自带Icon图标图文对应的网址,里面的图标已经算非常全面了,用的时候可以找找看看

Flutter 图标Icon

描述部分
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';

class DetailsDescribe extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
        builder: (context,child,val){
           var datas = val.datas;
           return Container(
              color: Colors.white,
              child: Column(
                children: <Widget>[
                    _buildFlowers(datas),
                    _buildMaterial(datas),
                    _buildExpansionpanel(datas)
                    

                ],
              ),
            );
        }, 
    );
    
  }
  
  //花语
  Widget _buildFlowers(DetailsModelDatas datas){
     return Padding(
        padding: EdgeInsets.symmetric(horizontal: 10.0),
        child: Container(
            padding: EdgeInsets.only(top: 10.0),
            child: Row(
               children: <Widget>[
                 Expanded(
                    flex: 1,
                    child: Container(
                       alignment: Alignment.topLeft,
                       child: Text("花语",
                        style:TextStyle(
                          fontWeight:FontWeight.w600
                        )
                       ),
                    ),
                 ),
                 Expanded(
                    flex: 9,
                    child: Container(
                        padding: EdgeInsets.only(bottom: 8.0),
                        decoration: BoxDecoration(
                           border: Border(
                             bottom: BorderSide(width: 1,color:Colors.black12)
                           ) 
                        ),
                        child: Text(
                          datas.huaYu,
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                    )
                    
                 )
               ],
            ),  
        ),
     );
  }
  
  //材料
  Widget _buildMaterial(DetailsModelDatas datas){
     return Padding(
        padding: EdgeInsets.symmetric(horizontal: 10.0),
        child: Container(
            padding: EdgeInsets.only(top: 10.0),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
               children: <Widget>[
                 Expanded(
                    flex: 1,
                    child: Container(
                       padding: EdgeInsets.only(bottom: 8.0),
                       alignment: Alignment.topLeft,
                       child: Text("材料",
                        style:TextStyle(
                          fontWeight:FontWeight.w600
                        )
                       ),
                    ),
                 ),
                 Expanded(
                    flex: 9,
                    child: Container(
                        padding: EdgeInsets.only(bottom: 8.0),
                        decoration: BoxDecoration(
                           border: Border(
                             bottom: BorderSide(width: 1,color:Colors.black12)
                           ) 
                        ),
                        child: Text(
                          datas.stuff,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ),
                    )
                    
                 )
               ],
            ),  
        ),
     );
  }
  //配送
  Widget _buildExpansionpanel(DetailsModelDatas datas){
     return Padding(
        padding: EdgeInsets.symmetric(horizontal: 0.0),
        child: Container(
          
           child: Container(
                  margin: EdgeInsets.all(0.0),
                  padding: EdgeInsets.all(0.0),
                  child: ExpansionTile(
                  title: ListTile(
                    contentPadding: EdgeInsets.all(0),
                    leading: Text("配送",
                          style:TextStyle(
                              fontSize: 14.0,
                              fontWeight:FontWeight.w600
                            )
                    ),
                    title: Text(
                              datas.deliveryArea,
                              maxLines: 1,
                              overflow: TextOverflow.ellipsis,
                              style:TextStyle(
                                fontSize: 14.0,
                              
                              )
                            ),
                  ),
                  children: <Widget>[
                    Container(
                        padding: EdgeInsets.only(bottom: 10.0),
                        child: Text(datas.deliveryArea),
                    )
                  ],
              ),
           )
           
        )
     );

  }
}

描述部分就注意一下这个ExpansionTile可展开的ListTile组件,还是比较常用的.

选择/配送
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';
import 'package:city_pickers/city_pickers.dart';

class DetailsDelivery extends StatelessWidget {
  

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
        builder: (context,child,val){
           var datas = val.datas;
           return Container(
              color: Colors.white,
              child: Column(
                children: <Widget>[
                  datas.itemSKUs != null ?  _buildFlowers(context,datas) : SizedBox(height: 0.1,),
                   _buildPeisong(context,"送至", "请选择配送地区")
                ],
              ),
            );
        }, 
    );
  }

 Widget _buildFlowers(BuildContext context,DetailsModelDatas datas){
     return Padding(
        padding: EdgeInsets.symmetric(horizontal: 10.0),
        child: Container(
            padding: EdgeInsets.only(top: 10.0),
            child: Row(
               children: <Widget>[
                 Expanded(
                    flex: 1,
                    child: Container(
                       alignment: Alignment.centerLeft,
                       padding: EdgeInsets.only(bottom: 8.0),
                       child: Text("已选",
                        style:TextStyle(
                          fontWeight:FontWeight.w600
                        )
                       ),
                    ),
                 ),
                 Expanded(
                    flex: 8,
                    child: Container(
                        padding: EdgeInsets.only(bottom: 8.0),
                        decoration: BoxDecoration(
                           border: Border(
                             bottom: BorderSide(width: 1,color:Colors.black12)
                           ) 
                        ),
                        child: Text(
                          datas.itemName,
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                    )
                    
                 ),
                 Expanded(
                    flex: 1,
                    child: Container(
                       alignment: Alignment.centerRight,
                       child: InkWell(
                          onTap: ()=> _onBottomSheet(context,datas),
                          child: Icon(Icons.more_horiz,
                            size: 30.0,
                          ),
                       ),
                    ),
                 )
               ],
            ),  
        ),
     );
  }
 

  //配送
  Widget _buildPeisong(BuildContext context,String title,String des){
     return Padding(
        padding: EdgeInsets.symmetric(horizontal: 10.0),
        child: Container(
            padding: EdgeInsets.only(top: 10.0),
            child: Row(
               children: <Widget>[
                 Expanded(
                    flex: 1,
                    child: Container(
                       padding: EdgeInsets.only(bottom: 8.0),
                       alignment: Alignment.centerLeft,
                       child: Text(title,
                        style:TextStyle(
                          fontWeight:FontWeight.w600
                        )
                       ),
                    ),
                 ),
                 Expanded(
                    flex: 8,
                    child: Container(
                        padding: EdgeInsets.only(bottom: 8.0),
                        
                        child: Text(
                          des,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ),
                    )
                    
                 ),
                 Expanded(
                    flex: 1,
                    child: Container(
                       alignment: Alignment.centerRight,
                       child: InkWell(
                          onTap: () async {
                            print("选择配置地址");
                            Result result = await CityPickers.showCityPicker(
                              context: context,
                            );
                            print("选择地址结果是: ${result}");
                          },
                          child: Icon(Icons.more_horiz,
                            size: 30.0,
                          ),
                       ),
                    ),
                 )
               ],
            ),  
        ),
     );
  }


  //商品选择弹出框
  void _onBottomSheet(BuildContext context,DetailsModelDatas datas){
     showModalBottomSheet(
         context: context,
         builder: (context){
            return Stack(
               children: <Widget>[
                   Container(
                      color: Color(0xFF737373),
                      height: MediaQuery.of(context).size.height * 0.55,
                      child: Container(
                        color: Colors.white,
                        child: Column(
                          children: <Widget>[
                              _buildBottomSelectGood(context, datas)
                          ],
                        )
                      ),
                  ),
                   Positioned(
                    bottom: 0,
                    left: 0,
                    child: Container(
                        height: 60.0,
                        child: Row(
                            children: <Widget>[
                                Container(
                                  width: MediaQuery.of(context).size.width/2,
                                  color: Color.fromRGBO(45, 60, 49, 1.0),
                                  alignment: Alignment.center,
                                  child: Text(
                                      "加入购物车",
                                      style:TextStyle(
                                        color:Colors.white,
                                        fontSize: 20.0
                                      )
                                  ),
                                ),
                                Container(
                                  width: MediaQuery.of(context).size.width/2,
                                  color: Colors.orangeAccent,
                                  alignment: Alignment.center,
                                  child: Text(
                                      "立即购买",
                                      style:TextStyle(
                                        color:Colors.white,
                                        fontSize: 20.0
                                      )
                                  ),
                                ) 
                            ],
                            
                        ),
                    )
                  )
               ],
            );
            
         }
     );
  }
  //商品选择弹出框UI
  Widget _buildBottomSelectGood(BuildContext context,DetailsModelDatas datas){
      return Container(
                  child:Column(
                    children: <Widget>[
                        _buildGoodsShowTop(context, datas),
                        _buildChangeGoods(context, datas),
                        SizedBox(height: 20.0,),
                        _buildGoodsCount(context),


                    ],
                  )
                  
            );
            
          
      
      
  }
  //头部商品展示
  Widget _buildGoodsShowTop(BuildContext context,DetailsModelDatas datas){
     return Container(
         padding: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 10.0),
         child:Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                 Container(
                    width: MediaQuery.of(context).size.width / 4,
                    height: MediaQuery.of(context).size.width / 4,
                    decoration: BoxDecoration(
                       border: Border.all(width: 1,color:Colors.black12),
                       borderRadius: BorderRadius.circular(3.0)
                    ),
                    child: Image.network(datas.coverImages[0]),

                 ),
                 
                 Container(
                    padding: EdgeInsets.only(top: 15.0),
                    width: MediaQuery.of(context).size.width / 2,
                    alignment: Alignment.centerLeft,
                    child:Column(
                       mainAxisAlignment: MainAxisAlignment.start,
                       children: <Widget>[
                          Container(
                            alignment: Alignment.centerLeft,
                            child: Text("¥${datas.price}",
                                style: TextStyle(
                                  fontSize: 20.0,
                                  color: Colors.deepOrange
                                ),
                              ),
                          ),
                          
                          SizedBox(height: 3.0,),
                          Container(
                            alignment: Alignment.centerLeft,
                            child: Text("已选  ${datas.itemName}"),
                          )
                          
                       ],
                    ),
                 ),
                 Container(
                    child: InkWell(
                       onTap: (){
                          print("关闭底部弹窗");
                          Navigator.pop(context);
                       },
                       child: Container(
                           alignment: Alignment.topRight,
                           child: Icon(Icons.close,
                             size: 30.0,
                           ),
                       )
                        
                    ),
                 )

              ],
           ) 
     );
          
  }

  //商品切换选择
  Widget _buildChangeGoods(BuildContext context,DetailsModelDatas datas){
    return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 15.0),
        child: Container(
           child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                  Container(
                     alignment: Alignment.centerLeft,
                     child: Text("选择"),
                  ),
                  SizedBox(height: 10.0,),
                  Wrap(
                    alignment: WrapAlignment.spaceBetween,
                    spacing: 10.0,
                    runSpacing: 10.0,
                    children: _buildChangeList(context, datas.itemSKUs)
                  )
              ],
           ),
        ),
    );

  }
  //选择列表
  List<Widget> _buildChangeList(BuildContext context,List<DetailsModelDatasItemsku> itemList){
        List<Widget> list = new List();
        for(var i = 0; i < itemList.length; i++){
          list.add(
              Container(
                 
                 width: (MediaQuery.of(context).size.width - 60.0)/4,
                 height: 35.0,
                 color: Colors.black12,
                 alignment: Alignment.center,
                 child: InkWell(
                    onTap: (){},
                    child: Text(itemList[i].optionName),
                 ),
              )
          ); 
          
        }
        return list;

  }



  //商品数量加减
  Widget _buildGoodsCount(BuildContext context){
     return Padding(
       padding: const EdgeInsets.symmetric(horizontal: 15.0),
       child: Container(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
               Text("数量"),
               _addOrReduceWidget(context)

            ],
          ),
       ),
     );

  }
  //商品加减小组件
  Widget _addOrReduceWidget(BuildContext context){
      return Container(
         width: MediaQuery.of(context).size.width / 4.2,
         height: 30.0,
         child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
                //减
                Container(
                   width: 24.0,
                   height: 24.0,
                   alignment: Alignment.center,
                   decoration: BoxDecoration(
                      color: Colors.black26,
                      borderRadius: BorderRadius.circular(12.0)
                   ),
                   child: Text("-",
                     style:TextStyle(
                        fontSize: 18.0,
                        color:Colors.white
                     )
                   ),
                ),
                Container(
                   child: Text("1"),
                ),
                Container(
                   width: 24.0,
                   height: 24.0,
                   alignment: Alignment.center,
                   decoration: BoxDecoration(
                      color: Colors.black26,
                      borderRadius: BorderRadius.circular(12.0)
                   ),
                   child: Text("+",
                     style:TextStyle(
                        fontSize: 18.0,
                        color:Colors.white
                     )
                   ),
                ),

            ],
         ),
      );
  }
}

这里面代码就比较多了,主要是我将这个选择商品规格和数量的底部sheet和这个省市区选择放在了一起了。 这里面注意这个底部弹出框是用这个: showModalBottomSheet,非常好用,不像以前原生要做个底部自定义弹窗(唉)。 还有就是我的省市区选择是用的国人写的插件city_pickers,挺好的,简单方便。

订单评价
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';

class DetailsEvaluate extends StatelessWidget {
  

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
        builder: (context,child,val){
           var datas = val.datas;
           return Container(
              color: Colors.white,
              child: 
               //判断是否有评价
                datas.comments != null ?
                  Column(
                    children: <Widget>[
                        _buildTopTitle(context, datas),
                        _buildEvaluates(context, datas.comments.itemComments),
                        SizedBox(height: 10.0,),
                        Container(
                           alignment: Alignment.center,
                           child: RaisedButton(
                              padding: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
                              onPressed: (){},
                              child: Text("查看更多评价"),
                           ),
                        )
                        

                    ],
                ):Container(
                   child: Center(
                      child: Text("暂无评价"),
                   ),
                )
           );
        },
    );
  }

  //顶部评价
  Widget _buildTopTitle(BuildContext context,DetailsModelDatas datas){
      return Padding(
        padding: EdgeInsets.all(10.0),
        child: Container(
           child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                 Container(
                    child: Text("订单评价",
                        style:TextStyle(
                           fontSize: 20.0,
                           fontWeight: FontWeight.w600
                        )
                    ),
                 ),
                 Container(
                    child: Text(
                      "最近已有${datas.comments.commentCount}条评价>"
                    ),
                 )
              ],
           ),
        ),
      );
  }

  //评价列表
  Widget _buildEvaluates(BuildContext context,List<DetailsModelDatasCommantsItemcommants> itemComments){
       return Container(
           child: Column(
              children: _buildEvaluateList(context, itemComments),
           ),
       );

  }
  List<Widget> _buildEvaluateList(BuildContext context,List<DetailsModelDatasCommantsItemcommants> itemComments){
        List<Widget> list = new List();
        for(var i = 0; i < itemComments.length; i++){
          list.add(
              _buildEvaluateItem(context, itemComments[i])
          ); 
          
        }
        return list;

  }
  //评价项
  Widget _buildEvaluateItem(BuildContext context,DetailsModelDatasCommantsItemcommants commant){
      return Container(
         padding: EdgeInsets.fromLTRB(10.0, 20.0, 10.0, 10.0),
         decoration: BoxDecoration(
            border: Border(
               top: BorderSide(width: 1,color: Colors.black12)
            )
         ),
         child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
                 Container(
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: <Widget>[
                           Row(
                              children: <Widget>[
                                 Container(
                                    width: 30.0,
                                    height: 30.0,
                                    
                                    child: ClipOval(
                                      child: Image.network(commant.userHeadImg),
                                    ),
                                    
                                 ),
                                 SizedBox(width: 3.0,),
                                 Text(commant.nickName)
                              ],
                           ),
                           Container(
                              child: _buildStars(context,commant.commentGrade),
                           )
                        ],
                    ),
                 ),
                 SizedBox(height: 10.0,),
                 //评价语
                 Container(
                    width: MediaQuery.of(context).size.width * 0.8,
                    
                    alignment: Alignment.centerLeft,
                    child: Text(
                       commant.commentContent
                    ),
                 ),
                 SizedBox(height: 10.0,),
                 //评价图片
               commant.commentImgs != null ?  Container(
                    alignment: Alignment.centerLeft,
                    width: 150.0,
                    child: Image.network(commant.commentImgs[0],
                      fit: BoxFit.fitWidth,
                    ),
                 ): SizedBox(height: 2.0,),
                 SizedBox(height: 8.0,),
                 //地址
                 Container(
                    child: Row(
                       children: <Widget>[
                          Container(
                             child: Icon(Icons.place,
                               size: 24.0,
                               color: Colors.black45,
                             ),
                          ),
                          Container(
                             child: Text(commant.commentAddress,
                               
                             ),
                          )
                       ],
                    ),
                 )
            ],
         ),
      );
  }

 Widget _buildStars(BuildContext context,int commentGrade){
    List<Widget> lists = List();
    for(var i = 0; i < commentGrade; i++){
       lists.add(
          Container(
             child: Row(
               children: <Widget>[
                  Icon(Icons.star,
                      color: Colors.orangeAccent,
                      size: 20.0,
                      ),
                  SizedBox(width: 2.0,),
               ],
             ),
          )
          
       );
    }
   
    return Container(
        child: Row(
           children: lists
        ),
    );
 }

}

权当练习布局了

为什么选择我们
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';

class DetailsCompany extends StatelessWidget {
 

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
             builder: (context,child,val){
                var datas = val.datas;
                return  Container(
                    color: Colors.white,
                    child: Column(
                      children: <Widget>[
                          Container(
                            padding: EdgeInsets.only(top: 20.0),
                            child: Center(
                                child: Text(datas.wayChooseUs.subject),
                            ),
                          ),
                          _buildBrands(context, datas.wayChooseUs.titleTextImgs)
                      ],
                    ),
                  );
              },
                
  );
   
}

 //圆形图片
 Widget _buildBrands(BuildContext context,List<DetailsModelDatasWaychooseusTitletextimg> titleTextImgs){
      return Padding(
         padding: EdgeInsets.all(20.0),
         child: Container(
            child: Wrap(
               spacing: 30.0,
               runSpacing: 30.0,
               children: _buildCompanyList(context, titleTextImgs),
            ),
         ),
      );
  }
  
   List<Widget> _buildCompanyList(BuildContext context,List<DetailsModelDatasWaychooseusTitletextimg> titleTextImgs){
        List<Widget> list = new List();
        for(var i = 0; i < titleTextImgs.length; i++){
          list.add(
             Container(
                width: (MediaQuery.of(context).size.width - 100.0)/3,
                child: Column(
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: <Widget>[
                      Container(
                         child: ClipOval(
                            child: Image.network(titleTextImgs[i].image),
                         ),
                      ),
                      SizedBox(height: 2.0,),
                      Container(
                         alignment: Alignment.center,
                         child: Text(titleTextImgs[i].title),
                      )
                   ],
                ),
             )
          ); 
          
        }
        return list;

  }
}

熟能生巧,写多了,这种布局写起来就没什么难度了。

图文详情
import 'package:flutter/material.dart';
import 'package:provide/provide.dart';
import '../../provide/details_provide.dart';
import '../../model/details_model.entity.dart';

class DetailsImgText extends StatelessWidget {
  

  @override
  Widget build(BuildContext context) {
    return Provide<DetailsPageProvide>(
         builder: (context,child,val){
            var datas = val.datas;
            return Container(
              color: Colors.white,
              child: Column(
                 children: <Widget>[
                    Container(
                       alignment: Alignment.centerLeft,
                       padding: EdgeInsets.all(15.0),
                       child: Text("图文详情"),
                    ),
                    _buildImages(context, datas.itemImages)

                 ],
              )
            );
         },
    );
    
  }

  //循环图片
  Widget _buildImages(BuildContext context,List<String> itemImage){
   
     List<Widget> lists = List();
     for(var i = 0; i < itemImage.length; i++){
        lists.add(
           Container(
              width: MediaQuery.of(context).size.width,
              child: Image.network(itemImage[i],
                fit: BoxFit.fitWidth,
              ),
           )
        );
     }
     return Column(
         children: lists,
     );

  }

}

给图片选择一个填充方式: fit:BoxFit.fitWidth.

底部购物车栏
import 'package:flutter/material.dart';

class DetailsBottom extends StatelessWidget {
  const DetailsBottom({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var itemW = MediaQuery.of(context).size.width / 6;
    return Container(
      color: Colors.white,
      width: MediaQuery.of(context).size.width,
      height: 60.0,
      child: Row(
          children: <Widget>[
             //客服
             InkWell(
               onTap: (){
                 print("点击了客服");
               },
               child: Container(
                      width: itemW,
                      decoration: BoxDecoration(
                        border: Border(
                            right: BorderSide(width: 1,color: Colors.black38)
                        )
                      ),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Icon(Icons.phone_iphone,
                            color: Colors.black45,
                            size: 30.0,
                          ),
                          Text("客服")
                        ],
                      ),
                  ),
             ),
             
             Container(
                width: itemW,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                     Icon(Icons.shopping_cart,
                      size: 30.0,
                      color: Colors.black45,
                     ),
                     Text("购物车")
                  ],
                ),
             ),
             Container(
               width: 2*itemW,
               color: Color.fromRGBO(45, 60, 49, 1.0),
               alignment: Alignment.center,
               child: Text(
                  "加入购物车",
                  style:TextStyle(
                    color:Colors.white
                  )
               ),
             ),
             Container(
               width: 2*itemW,
               color: Colors.orangeAccent,
               alignment: Alignment.center,
               child: Text(
                  "立即购买",
                  style:TextStyle(
                    color:Colors.white
                  )
               ),
             )
          ],
      ),
    );
  }
}

这个主要就是在嵌入商品详情页的时候,是要悬浮在详情页其它组件之上且在底部:

 Positioned(
                             bottom: 0,
                             left: 0,
                             child: DetailsBottom(),
                          )
商品详情页就这么多东西,然后其中的各种数据交互的逻辑都还没做,这个得和后面的购物车结合起来做。最后这个项目完成后代码会上传到gitHub上。 其次其中写得不好的请指正,共同进步。

下一篇购物车界面

推荐阅读更多精彩内容

  • “兵器是磨出来的,士兵是练出来的”——中国拓展训练哲学理论实践撰写大师何宜宣~(˶‾᷄ꈊ‾᷅˵)~今天我们去...
    Hannah宣阅读 276评论 0 2
  • https://leetcode.com/problems/two-sum/ Given an array of ...
    羊yang678阅读 77评论 0 1