You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何创建3:1宽度比的自适应高度双列卡片

解决Flutter卡片右侧列高度填充问题

你的问题核心是右侧红色背景容器没有填满Row的整个高度,导致上下出现空白。只需以下两处修改即可解决:

  1. 给外层的Row添加crossAxisAlignment: CrossAxisAlignment.stretch,强制两个子组件拉伸至Row的最大高度;
  2. 将右侧Column的mainAxisAlignment改为MainAxisAlignment.spaceBetween,让内容自动分布在顶部和底部,红色背景会自然填满整个高度(如果希望内容全部靠上,也可以保留MainAxisAlignment.start,但要给Column加上mainAxisSize: MainAxisSize.max)。

修改后的完整代码:

Card(
  elevation: 2,
  clipBehavior: Clip.antiAlias,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
  margin: const EdgeInsets.only(top: 10, bottom: 0, left: 10, right: 10),
  child: Row(
    // 新增:让子组件拉伸填满Row高度
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Flexible(
        flex: 3,
        fit: FlexFit.tight,
        child: Padding(
          padding: const EdgeInsets.symmetric(
            horizontal: 8.0,
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TimelineTile(
                alignment: TimelineAlign.start,
                isFirst: true,
                afterLineStyle: const LineStyle(color: TruckerAppTheme.grey, thickness: 2),
                indicatorStyle:
                    IndicatorStyle(color: Colors.white, padding: const EdgeInsets.all(0), iconStyle: IconStyle(fontSize: 28, iconData: Icons.location_on_rounded, color: TruckerAppTheme.grey)),
                endChild: Container(
                  padding: const EdgeInsets.fromLTRB(8.0, 8, 0, 0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      SizedBox(
                          child: Text(widget.load.pickupCity != null ? "${widget.load.pickupCity}, ${widget.load.pickupState}" : "${widget.load.pickupState}",
                              overflow: TextOverflow.visible, style: TruckerAppTheme.locationText)),
                      SizedBox(
                          child: Text(DateFormat('dd-MMM-yy').format(DateFormat('yyyy-MM-dd').parse(widget.load.pickupTimeStamp!)).toString(),
                              overflow: TextOverflow.ellipsis, style: TruckerAppTheme.bodyNormalSmall)),
                    ],
                  ),
                ),
              ),
              TimelineTile(
                alignment: TimelineAlign.start,
                isLast: true,
                beforeLineStyle: const LineStyle(color: TruckerAppTheme.grey, thickness: 2),
                indicatorStyle:
                    IndicatorStyle(color: Colors.white, padding: const EdgeInsets.all(0), iconStyle: IconStyle(fontSize: 28, iconData: Icons.flag_rounded, color: TruckerAppTheme.grey)),
                endChild: Container(
                  padding: EdgeInsets.fromLTRB(8.0, 8, 0, (widget.load.dropTimeStamp != null) ? 0 : 7),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      SizedBox(
                          child: Text(widget.load.dropCity != null ? "${widget.load.dropCity}, ${widget.load.dropState}" : "${widget.load.dropState}",
                              overflow: TextOverflow.visible, style: TruckerAppTheme.locationText)),
                      (widget.load.dropTimeStamp != null)
                          ? Text(DateFormat('dd-MMM-yy').format(DateFormat('yyyy-MM-dd').parse(widget.load.dropTimeStamp!)).toString(),
                              overflow: TextOverflow.ellipsis, style: TruckerAppTheme.bodyNormalSmall)
                          : Container(),
                    ],
                  ),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  widget.load.materialType == ""
                      ? Flexible(
                          child: Padding(
                          padding: const EdgeInsets.only(bottom: 8.0),
                          child: Text(
                            "${widget.load.loadWeight} ${widget.load.loadUnits.toString()[0] + widget.load.loadUnits.toString().substring(1).toLowerCase()} • ${VehicleTypeMapping().vehicleTypeMapping[widget.load.vehicleType!]!.value}",
                            style: TruckerAppTheme.quantityText,
                          ),
                        ))
                      : Flexible(
                          child: Padding(
                          padding: const EdgeInsets.only(bottom: 8.0),
                          child: Text(
                            "${widget.load.loadWeight} ${widget.load.loadUnits.toString()[0] + widget.load.loadUnits.toString().substring(1).toLowerCase()} • ${widget.load.materialType} • ${VehicleTypeMapping().vehicleTypeMapping[widget.load.vehicleType!]!.value}",
                            style: TruckerAppTheme.quantityText,
                          ),
                        )),
                ],
              )
            ],
          ),
        ),
      ),
      Flexible(
        flex: 1,
        fit: FlexFit.tight,
        child: Container(
          padding: const EdgeInsets.only(bottom: 8, top: 8, right: 8, left: 8),
          margin: EdgeInsets.only(right: 0, top: 0, bottom: 0, left: 1),
          decoration: BoxDecoration(color: TruckerAppTheme.primaryColor.withOpacity(0.5), borderRadius: BorderRadius.circular(0)),
          child: Column(
            // 修改:让内容分布在上下,背景填满高度
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    "Price",
                    style: TruckerAppTheme.quantityText,
                  ),
                  widget.load.perTonneAmount == null
                      ? Text(
                          "Pending",
                          style: TruckerAppTheme.pricePendingText,
                        )
                      : Text(
                          "₹ ${widget.load.perTonneAmount} Per Tonne",
                          style: TruckerAppTheme.pricePendingText,
                        ),
                ],
              ),
              Text(
                "Bid Now",
                style: TextStyle(fontSize: 14),
              ),
            ],
          ),
        ),
      )
    ],
  ),
)

另外,我把右侧的固定高度SizedBox(height:40)替换成了嵌套Column+MainAxisAlignment.spaceBetween的方式,这样布局会更自适应,不会出现固定高度导致的适配问题。

内容的提问来源于stack exchange,提问作者szervay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:47:08