ed94bbb1f573dd5dcd00505fab7cfb72.png
商品詳情頁完成--看看效果:
1111.gif
商品詳情頁布局
商品詳情頁一般都是這個商城app中布局最多的一個界面慷暂,也是各種交互比較多的界面,整整寫了一天才寫完(其實(shí)還沒完帕涌,后面有些無關(guān)緊要的圖片就沒有寫了)
還是一點(diǎn)來吧
首先是路由配置和數(shù)據(jù)獲取
路由配置:
Handler detailsHandler = Handler(
handlerFunc: (BuildContext context,Map<String,List<String>> params){
String itemCode = params["itemCode"].first;//傳遞請求參數(shù)
print("傳遞的itemCode是: ${itemCode}");
return DetailsPage(itemCode);
}
static String detailsPage = "/detailsPage";
router.define(detailsPage,handler: detailsHandler);
//使用:
onTap: (){
Application.router.navigateTo(context, "/detailsPage?itemCode=${sectionListItem.productCode}");
},
數(shù)據(jù)獲取:
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("暫無數(shù)據(jù)"),
);
}
}
)
);
}
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("點(diǎn)擊了輪播組件:${index}");
},
itemCount: coverImages.length,
pagination: buildSwiperPagintion(),
autoplay: true,
),
);
},
);
}
buildSwiperPagintion(){
return SwiperPagination(
builder: FractionPaginationBuilder(
color: Colors.white,
activeColor: Colors.orange
)
);
}
}
這個輪播插件還是挺好用的虎眨,就是這個Page指示器和app上的不一樣,由于這個插件只提供了兩種樣式,如果想要和app中的一樣需要自定義這個SwiperPagination, 后面完成后嗽桩,來試試自己自定義這個東東岳守。
頂部標(biāo)題和價格
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),
],
),
),
),
);
},
);
}
//標(biāo)題
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圖標(biāo)圖文對應(yīng)的網(wǎng)址湿痢,里面的圖標(biāo)已經(jīng)算非常全面了,用的時候可以找找看看
描述部分
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,"送至", "請選擇配送地區(qū)")
],
),
);
},
);
}
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("選擇地址結(jié)果是: ${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("關(guān)閉底部彈窗");
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;
}
//商品數(shù)量加減
Widget _buildGoodsCount(BuildContext context){
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("數(shù)量"),
_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
)
),
),
],
),
);
}
}
這里面代碼就比較多了譬重,主要是我將這個選擇商品規(guī)格和數(shù)量的底部sheet和這個省市區(qū)選擇放在了一起了。 這里面注意這個底部彈出框是用這個: showModalBottomSheet,非常好用罐氨,不像以前原生要做個底部自定義彈窗(唉)臀规。 還有就是我的省市區(qū)選擇是用的國人寫的插件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;
}
//評價項(xiàng)
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
),
);
}
}
權(quán)當(dāng)練習(xí)布局了
為什么選擇我們
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)
],
)
);
},
);
}
//循環(huán)圖片
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("點(diǎn)擊了客服");
},
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(),
)
商品詳情頁就這么多東西,然后其中的各種數(shù)據(jù)交互的邏輯都還沒做恰矩,這個得和后面的購物車結(jié)合起來做。最后這個項(xiàng)目完成后代碼會上傳到gitHub上憎蛤。 其次其中寫得不好的請指正外傅,共同進(jìn)步。
下一篇購物車界面