问题描述
我一直在尝试使用 row
和 column
在 Flutter 中定义定制卡片,但似乎无法获得与上图类似的固定格式布局(红线表示卡,只是在那里显示区域)。
例如
return Card(child: Column(
children: [
Row(
children: [
Column( children: [
Text('Riverside cafe...'),ratingbar(),],),ImageWidget(),Container(child: Text('Pubs & restaurants'),color : Colors.purple)
],
生成的卡片将显示在 listview
中,使用上面的 rows
和 columns
会导致区域大小因数据而异。
在我看来,使用 row
和 column
可能不是实现这一目标的最佳方式。有没有更好的办法?
解决方法
至于最好的,我想这由您和您的客户决定。
只要我一直在使用 Flutter,我就没有遇到过像 CSS 网格这样的东西,它非常适合这种情况。最接近的比较是 StaggeredGrid (https://pub.dev/packages/flutter_staggered_grid_view),但它提供的控制不如 CSS 网格多,而且似乎不太适合您的用例。
这是生成上述示例的 main.dart。代码质量并不完美,但希望您能很好地遵循它,它可以帮助您完成需要完成的工作。
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
static const String _title = 'Bespoke card example';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,home: MyHomePage(),);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Bespoke card example')),body: Center(
child: Wrap(runSpacing: 10.0,children: [
BespokeCard(title: 'Short name',width: 350),BespokeCard(
title: 'Riverside Cafe with a really long name',width: 350)
]),),);
}
}
class BespokeCard extends StatelessWidget {
final String title;
final double width;
BespokeCard({this.title,this.width});
@override
Widget build(BuildContext context) {
Widget _restaurantNameContainer = Container(
constraints: BoxConstraints(
minHeight: 0,maxHeight: 120,maxWidth: (500.0 - 40 - 175 + 1),minWidth: (500.0 - 40 - 175 + 1),child: AutoSizeText(
title,style: TextStyle(fontSize: 60),maxLines: 2,minFontSize: 10,stepGranularity: 0.1,overflow: TextOverflow.ellipsis,);
Widget _rightSideSection = Container(
width: 175,height: Size.infinite.height,child: Center(
child: Icon(
Icons.umbrella,size: 70,);
Widget _topSection = Flexible(
flex: 1,child: Row(
children: [
Flexible(
fit: FlexFit.tight,flex: 3,child: Padding(
padding: EdgeInsets.only(left: 40.0,top: 25.0),child: Column(
children: [
Flexible(child: Container(),flex: 1),_restaurantNameContainer,Text('* * * * *',style: TextStyle(fontSize: 70)),],_rightSideSection
],);
Widget _bottomSection = Container(
height: 70,width: Size.infinite.width,child: Center(
child: Text('Pubs & Restaurants',style: TextStyle(color: Colors.white,fontSize: 40)),color: Colors.purple);
Widget unfittedCard = Card(
child: SizedBox(
width: 500,height: 300,child: Column(
mainAxisSize: MainAxisSize.max,children: [_topSection,_bottomSection],));
return Container(
width: this.width,child: FittedBox(fit: BoxFit.fitWidth,child: unfittedCard));
}
}
注意:
- 注意 flexFit(紧或松)属性:https://api.flutter.dev/flutter/widgets/Flexible/fit.html
- 您可以为所有的flexibles定义固定比率,也可以将flexibles与Containers/SizedBoxes混合使用
- auto_size_text 包非常适合这种情况。 (将
auto_size_text: ^2.1.0
添加到您的依赖项) - 注意框约束。我需要它们来使标题自动调整大小的文本能够变高,而不必放在一个大容器中。
- Fitted box 真的很方便,而且在颤动时很容易缩放。