Commit 2caf589685277c324393bd60536dd9b8eedb7d33
1 parent
ad37b653
feat:商品列表图片优化
Showing
2 changed files
with
103 additions
and
141 deletions
lib/pages/shop/home/widgets/product_item.dart
| @@ -4,8 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | @@ -4,8 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 4 | import 'package:wow_english/models/product_entity.dart'; | 4 | import 'package:wow_english/models/product_entity.dart'; |
| 5 | 5 | ||
| 6 | class ProductItem extends StatelessWidget { | 6 | class ProductItem extends StatelessWidget { |
| 7 | - const ProductItem({super.key, | ||
| 8 | - required this.onTap, this.entity}); | 7 | + const ProductItem({super.key, required this.onTap, this.entity}); |
| 9 | 8 | ||
| 10 | final ProductEntity? entity; | 9 | final ProductEntity? entity; |
| 11 | 10 | ||
| @@ -15,52 +14,27 @@ class ProductItem extends StatelessWidget { | @@ -15,52 +14,27 @@ class ProductItem extends StatelessWidget { | ||
| 15 | Widget build(BuildContext context) { | 14 | Widget build(BuildContext context) { |
| 16 | return Container( | 15 | return Container( |
| 17 | decoration: BoxDecoration( | 16 | decoration: BoxDecoration( |
| 18 | - borderRadius: BorderRadius.circular(10.r), | ||
| 19 | - border: Border.all( | ||
| 20 | - width: 1.0, | ||
| 21 | - color: Colors.black | ||
| 22 | - ) | ||
| 23 | - // image: DecorationImage( | ||
| 24 | - // image: AssetImage( | ||
| 25 | - // ''.assetPng, | ||
| 26 | - // ), | ||
| 27 | - // fit: BoxFit.fill | ||
| 28 | - // ) | ||
| 29 | - ), | ||
| 30 | - padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 16.h), | 17 | + borderRadius: BorderRadius.circular(10.r), |
| 18 | + border: Border.all(width: 1.0, color: Colors.black)), | ||
| 19 | + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), | ||
| 31 | child: Row( | 20 | child: Row( |
| 32 | mainAxisAlignment: MainAxisAlignment.spaceBetween, | 21 | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| 33 | children: [ | 22 | children: [ |
| 34 | Container( | 23 | Container( |
| 35 | - width: 124.w, | 24 | + width: 124.w, // 图片宽度 |
| 25 | + height: 124.h, // 图片高度 | ||
| 36 | decoration: BoxDecoration( | 26 | decoration: BoxDecoration( |
| 37 | - border: Border.all( | ||
| 38 | - width: 1.0, | ||
| 39 | - color: const Color(0xFF333333), | ||
| 40 | - ), | ||
| 41 | - image: DecorationImage( | ||
| 42 | - image: NetworkImage(entity?.picUrl ?? ''), | ||
| 43 | - ) | 27 | + borderRadius: BorderRadius.circular(5), |
| 28 | + // 圆角为5 | ||
| 29 | + border: Border.all(width: 1.w, color: const Color(0xFF333333)), | ||
| 30 | + // 边框宽度为1 | ||
| 31 | + // 使用ClipRRect圆角会有间隙,ClipRRect在裁剪时可能会导致圆角部分的边框显示不完整。 | ||
| 32 | + image: DecorationImage( | ||
| 33 | + image: NetworkImage(entity?.picUrl ?? ''), // 图片地址 | ||
| 34 | + fit: BoxFit.cover, // 图片填充方式 | ||
| 35 | + ), | ||
| 44 | ), | 36 | ), |
| 45 | ), | 37 | ), |
| 46 | - // CachedNetworkImage( | ||
| 47 | - // imageUrl: entity?.picUrl ?? '', | ||
| 48 | - // fit: BoxFit.fill, | ||
| 49 | - // imageBuilder: (context, imageProvider) => | ||
| 50 | - // Container( | ||
| 51 | - // decoration: BoxDecoration( | ||
| 52 | - // border: Border.all( | ||
| 53 | - // width: 1.0, | ||
| 54 | - // color: const Color(0xFF333333), | ||
| 55 | - // ), | ||
| 56 | - // borderRadius: BorderRadius.circular(5.0), | ||
| 57 | - // ), | ||
| 58 | - // ), | ||
| 59 | - // placeholder: (context, url) => const CircularProgressIndicator(), | ||
| 60 | - // // errorWidget: (context, url, error) => const Icon(Icons.error), | ||
| 61 | - // height: 124.h, | ||
| 62 | - // width: 124.w, | ||
| 63 | - // ), | ||
| 64 | 21.5.horizontalSpace, | 38 | 21.5.horizontalSpace, |
| 65 | Expanded( | 39 | Expanded( |
| 66 | child: Column( | 40 | child: Column( |
| @@ -72,29 +46,24 @@ class ProductItem extends StatelessWidget { | @@ -72,29 +46,24 @@ class ProductItem extends StatelessWidget { | ||
| 72 | softWrap: true, | 46 | softWrap: true, |
| 73 | textAlign: TextAlign.left, | 47 | textAlign: TextAlign.left, |
| 74 | style: TextStyle( | 48 | style: TextStyle( |
| 75 | - fontSize: 12.sp, | ||
| 76 | - color: const Color(0xFF333333) | ||
| 77 | - ), | 49 | + fontSize: 16.sp, color: const Color(0xFF333333)), |
| 78 | ), | 50 | ), |
| 79 | RichText( | 51 | RichText( |
| 80 | - text: TextSpan( | ||
| 81 | - children:[ | ||
| 82 | - TextSpan( | ||
| 83 | - text: '¥', | ||
| 84 | - style: TextStyle( | ||
| 85 | - fontSize: 21.sp, | ||
| 86 | - color: const Color(0xFFF51A1A), | ||
| 87 | - ) | ||
| 88 | - ), | ||
| 89 | - TextSpan( | ||
| 90 | - text: entity?.price?.toString() ?? '', | ||
| 91 | - style: TextStyle( | ||
| 92 | - fontSize: 40.sp, | ||
| 93 | - color: const Color(0xFFF51A1A), | ||
| 94 | - ), | ||
| 95 | - ) | ||
| 96 | - ] | ||
| 97 | - ), | 52 | + text: TextSpan(children: [ |
| 53 | + TextSpan( | ||
| 54 | + text: '¥', | ||
| 55 | + style: TextStyle( | ||
| 56 | + fontSize: 21.sp, | ||
| 57 | + color: const Color(0xFFF51A1A), | ||
| 58 | + )), | ||
| 59 | + TextSpan( | ||
| 60 | + text: entity?.price?.toString() ?? '', | ||
| 61 | + style: TextStyle( | ||
| 62 | + fontSize: 40.sp, | ||
| 63 | + color: const Color(0xFFF51A1A), | ||
| 64 | + ), | ||
| 65 | + ) | ||
| 66 | + ]), | ||
| 98 | ), | 67 | ), |
| 99 | GestureDetector( | 68 | GestureDetector( |
| 100 | onTap: () { | 69 | onTap: () { |
| @@ -107,8 +76,7 @@ class ProductItem extends StatelessWidget { | @@ -107,8 +76,7 @@ class ProductItem extends StatelessWidget { | ||
| 107 | border: Border.all( | 76 | border: Border.all( |
| 108 | color: const Color(0xFF333333), | 77 | color: const Color(0xFF333333), |
| 109 | width: 1.0, | 78 | width: 1.0, |
| 110 | - ) | ||
| 111 | - ), | 79 | + )), |
| 112 | padding: EdgeInsets.symmetric( | 80 | padding: EdgeInsets.symmetric( |
| 113 | vertical: 1.h, | 81 | vertical: 1.h, |
| 114 | horizontal: 26.5.w, | 82 | horizontal: 26.5.w, |
| @@ -116,9 +84,7 @@ class ProductItem extends StatelessWidget { | @@ -116,9 +84,7 @@ class ProductItem extends StatelessWidget { | ||
| 116 | child: Text( | 84 | child: Text( |
| 117 | '立即购买', | 85 | '立即购买', |
| 118 | style: TextStyle( | 86 | style: TextStyle( |
| 119 | - fontSize: 10.sp, | ||
| 120 | - color: const Color(0xFF333333) | ||
| 121 | - ), | 87 | + fontSize: 10.sp, color: const Color(0xFF333333)), |
| 122 | ), | 88 | ), |
| 123 | ), | 89 | ), |
| 124 | ) | 90 | ) |
| @@ -129,4 +95,4 @@ class ProductItem extends StatelessWidget { | @@ -129,4 +95,4 @@ class ProductItem extends StatelessWidget { | ||
| 129 | ), | 95 | ), |
| 130 | ); | 96 | ); |
| 131 | } | 97 | } |
| 132 | -} | ||
| 133 | \ No newline at end of file | 98 | \ No newline at end of file |
| 99 | +} |
lib/pages/shopping/view.dart
| @@ -19,33 +19,31 @@ Widget buildRadioOption({ | @@ -19,33 +19,31 @@ Widget buildRadioOption({ | ||
| 19 | required bool isSelected, | 19 | required bool isSelected, |
| 20 | required ValueChanged onSelect, | 20 | required ValueChanged onSelect, |
| 21 | }) { | 21 | }) { |
| 22 | - return | ||
| 23 | - GestureDetector( | ||
| 24 | - onTap: () { | ||
| 25 | - onSelect(value); | ||
| 26 | - }, | ||
| 27 | - child: Row( | ||
| 28 | - crossAxisAlignment: CrossAxisAlignment.center, | ||
| 29 | - children: [ | ||
| 30 | - Image(image: icon, width: 25.0.w, height: 25.0.h, fit: BoxFit.contain), | ||
| 31 | - const SizedBox(width: 10.0), | ||
| 32 | - Expanded( | ||
| 33 | - child: Text( | ||
| 34 | - text, | ||
| 35 | - style: TextStyle(color: const Color(0xFF333333), fontSize: 12.5.sp), | ||
| 36 | - ), | 22 | + return GestureDetector( |
| 23 | + onTap: () { | ||
| 24 | + onSelect(value); | ||
| 25 | + }, | ||
| 26 | + child: Row( | ||
| 27 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 28 | + children: [ | ||
| 29 | + Image(image: icon, width: 25.0.w, height: 25.0.h, fit: BoxFit.contain), | ||
| 30 | + const SizedBox(width: 10.0), | ||
| 31 | + Expanded( | ||
| 32 | + child: Text( | ||
| 33 | + text, | ||
| 34 | + style: TextStyle(color: const Color(0xFF333333), fontSize: 12.5.sp), | ||
| 37 | ), | 35 | ), |
| 38 | - Image( | ||
| 39 | - image: isSelected | ||
| 40 | - ? AssetImage('checked'.assetPng) | ||
| 41 | - : AssetImage('unchecked'.assetPng), | ||
| 42 | - width: 22.0.w, | ||
| 43 | - height: 22.0.h, | ||
| 44 | - ), | ||
| 45 | - ], | ||
| 46 | - ), | ||
| 47 | - ); | ||
| 48 | - | 36 | + ), |
| 37 | + Image( | ||
| 38 | + image: isSelected | ||
| 39 | + ? AssetImage('checked'.assetPng) | ||
| 40 | + : AssetImage('unchecked'.assetPng), | ||
| 41 | + width: 22.0.w, | ||
| 42 | + height: 22.0.h, | ||
| 43 | + ), | ||
| 44 | + ], | ||
| 45 | + ), | ||
| 46 | + ); | ||
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | class ShoppingPage extends StatelessWidget { | 49 | class ShoppingPage extends StatelessWidget { |
| @@ -83,22 +81,22 @@ class _ShoppingView extends StatelessWidget { | @@ -83,22 +81,22 @@ class _ShoppingView extends StatelessWidget { | ||
| 83 | child: Row( | 81 | child: Row( |
| 84 | crossAxisAlignment: CrossAxisAlignment.start, | 82 | crossAxisAlignment: CrossAxisAlignment.start, |
| 85 | children: [ | 83 | children: [ |
| 86 | - CachedNetworkImage( | ||
| 87 | - imageUrl: bloc.productData?.detailPicUrl ?? '', | ||
| 88 | - imageBuilder: (context, imageProvider) => Container( | ||
| 89 | - decoration: BoxDecoration( | ||
| 90 | - image: DecorationImage( | ||
| 91 | - image: imageProvider, | ||
| 92 | - fit: BoxFit.cover, | ||
| 93 | - ), | ||
| 94 | - borderRadius: BorderRadius.circular(5.0), | 84 | + Container( |
| 85 | + width: 210.w, // 图片宽度 | ||
| 86 | + height: 210.h, // 图片高度 | ||
| 87 | + decoration: BoxDecoration( | ||
| 88 | + borderRadius: BorderRadius.circular(5.w), | ||
| 89 | + // 圆角为5 | ||
| 90 | + border: | ||
| 91 | + Border.all(width: 1.w, color: const Color(0xFF333333)), | ||
| 92 | + // 边框宽度为1 | ||
| 93 | + // 使用ClipRRect圆角会有间隙,ClipRRect在裁剪时可能会导致圆角部分的边框显示不完整。 | ||
| 94 | + image: DecorationImage( | ||
| 95 | + image: NetworkImage(bloc.productData?.detailPicUrl ?? ''), | ||
| 96 | + // 图片地址 | ||
| 97 | + fit: BoxFit.cover, // 图片填充方式 | ||
| 95 | ), | 98 | ), |
| 96 | ), | 99 | ), |
| 97 | - placeholder: (context, url) => | ||
| 98 | - const CircularProgressIndicator(), | ||
| 99 | - // errorWidget: (context, url, error) => const Icon(Icons.error), | ||
| 100 | - height: 210.0.h, | ||
| 101 | - width: 210.0.w, | ||
| 102 | ), | 100 | ), |
| 103 | const SizedBox(width: 35.5), | 101 | const SizedBox(width: 35.5), |
| 104 | Expanded(child: _paymentWidget()) | 102 | Expanded(child: _paymentWidget()) |
| @@ -117,26 +115,21 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | @@ -117,26 +115,21 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | ||
| 117 | crossAxisAlignment: CrossAxisAlignment.start, | 115 | crossAxisAlignment: CrossAxisAlignment.start, |
| 118 | children: [ | 116 | children: [ |
| 119 | RichText( | 117 | RichText( |
| 120 | - text: TextSpan( | ||
| 121 | - children: [ | ||
| 122 | - TextSpan( | ||
| 123 | - text: '套餐价格:', | ||
| 124 | - style: | ||
| 125 | - TextStyle(color: const Color(0xFF333333), fontSize: 16.5.sp) | ||
| 126 | - ), | ||
| 127 | - TextSpan( | ||
| 128 | - text: '¥${bloc.productData?.price ?? ''}', | ||
| 129 | - style: | ||
| 130 | - TextStyle(color: const Color(0xFFE5262A), fontSize: 16.5.sp) | ||
| 131 | - ), | ||
| 132 | - ] | ||
| 133 | - ), | 118 | + text: TextSpan(children: [ |
| 119 | + TextSpan( | ||
| 120 | + text: '套餐价格:', | ||
| 121 | + style: TextStyle( | ||
| 122 | + color: const Color(0xFF333333), fontSize: 16.5.sp)), | ||
| 123 | + TextSpan( | ||
| 124 | + text: '¥${bloc.productData?.price ?? ''}', | ||
| 125 | + style: TextStyle( | ||
| 126 | + color: const Color(0xFFE5262A), fontSize: 16.5.sp)), | ||
| 127 | + ]), | ||
| 134 | ), | 128 | ), |
| 135 | const SizedBox(height: 14.5), | 129 | const SizedBox(height: 14.5), |
| 136 | Text( | 130 | Text( |
| 137 | '套餐名称:${bloc.productData?.name}', | 131 | '套餐名称:${bloc.productData?.name}', |
| 138 | - style: | ||
| 139 | - TextStyle(color: const Color(0xFF333333), fontSize: 16.sp), | 132 | + style: TextStyle(color: const Color(0xFF333333), fontSize: 16.sp), |
| 140 | maxLines: 2, | 133 | maxLines: 2, |
| 141 | ), | 134 | ), |
| 142 | const SizedBox(height: 14.5), | 135 | const SizedBox(height: 14.5), |
| @@ -158,7 +151,8 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | @@ -158,7 +151,8 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | ||
| 158 | value: PaymentChannel.wechatPay.payChannelType, | 151 | value: PaymentChannel.wechatPay.payChannelType, |
| 159 | icon: AssetImage('weixin'.assetPng), | 152 | icon: AssetImage('weixin'.assetPng), |
| 160 | text: PaymentChannel.wechatPay.payChannelName, | 153 | text: PaymentChannel.wechatPay.payChannelName, |
| 161 | - isSelected: bloc.curPaymentChannel.payChannelType == PaymentChannel.wechatPay.payChannelType, | 154 | + isSelected: bloc.curPaymentChannel.payChannelType == |
| 155 | + PaymentChannel.wechatPay.payChannelType, | ||
| 162 | onSelect: (newValue) { | 156 | onSelect: (newValue) { |
| 163 | bloc.add(ChangePaymentChannelEvent(PaymentChannel.wechatPay)); | 157 | bloc.add(ChangePaymentChannelEvent(PaymentChannel.wechatPay)); |
| 164 | }, | 158 | }, |
| @@ -168,7 +162,8 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | @@ -168,7 +162,8 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | ||
| 168 | value: PaymentChannel.aliPay.payChannelType, | 162 | value: PaymentChannel.aliPay.payChannelType, |
| 169 | icon: AssetImage('zhifubao'.assetPng), | 163 | icon: AssetImage('zhifubao'.assetPng), |
| 170 | text: PaymentChannel.aliPay.payChannelName, | 164 | text: PaymentChannel.aliPay.payChannelName, |
| 171 | - isSelected: bloc.curPaymentChannel.payChannelType == PaymentChannel.aliPay.payChannelType, | 165 | + isSelected: bloc.curPaymentChannel.payChannelType == |
| 166 | + PaymentChannel.aliPay.payChannelType, | ||
| 172 | onSelect: (newValue) { | 167 | onSelect: (newValue) { |
| 173 | bloc.add(ChangePaymentChannelEvent(PaymentChannel.aliPay)); | 168 | bloc.add(ChangePaymentChannelEvent(PaymentChannel.aliPay)); |
| 174 | }, | 169 | }, |
| @@ -178,25 +173,26 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | @@ -178,25 +173,26 @@ Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>( | ||
| 178 | mainAxisAlignment: MainAxisAlignment.spaceBetween, | 173 | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| 179 | children: [ | 174 | children: [ |
| 180 | RichText( | 175 | RichText( |
| 181 | - text: TextSpan( | ||
| 182 | - children: [ | ||
| 183 | - const TextSpan( | ||
| 184 | - text: '需支付:', | ||
| 185 | - style: | ||
| 186 | - TextStyle(color: Color(0xFF333333), fontSize: 12.5, fontFamily: 'PingFangSC-Regular') | ||
| 187 | - ), | ||
| 188 | - TextSpan( | ||
| 189 | - text: '¥${bloc.productData?.price ?? ''}', | ||
| 190 | - style: | ||
| 191 | - TextStyle(color: const Color(0xFFE7383B), fontSize: 41.sp, fontFamily: 'PingFangSC-Regular') | ||
| 192 | - ), | ||
| 193 | - ] | ||
| 194 | - ), | 176 | + text: TextSpan(children: [ |
| 177 | + const TextSpan( | ||
| 178 | + text: '需支付:', | ||
| 179 | + style: TextStyle( | ||
| 180 | + color: Color(0xFF333333), | ||
| 181 | + fontSize: 12.5, | ||
| 182 | + fontFamily: 'PingFangSC-Regular')), | ||
| 183 | + TextSpan( | ||
| 184 | + text: '¥${bloc.productData?.price ?? ''}', | ||
| 185 | + style: TextStyle( | ||
| 186 | + color: const Color(0xFFE7383B), | ||
| 187 | + fontSize: 41.sp, | ||
| 188 | + fontFamily: 'PingFangSC-Regular')), | ||
| 189 | + ]), | ||
| 195 | ), | 190 | ), |
| 196 | // 确认支付按钮 | 191 | // 确认支付按钮 |
| 197 | GestureDetector( | 192 | GestureDetector( |
| 198 | onTap: () { | 193 | onTap: () { |
| 199 | - bloc.add(DoPayEvent(bloc.productData, bloc.curPaymentChannel)); | 194 | + bloc.add( |
| 195 | + DoPayEvent(bloc.productData, bloc.curPaymentChannel)); | ||
| 200 | }, | 196 | }, |
| 201 | child: Image( | 197 | child: Image( |
| 202 | width: 105.w, | 198 | width: 105.w, |