Flutter如何创建带图片的可复用卡片组件?
可复用带图片Flutter Card组件实现方案
问题背景
需要实现一个带图片的可复用Card组件,当前编写的ListViewCard组件尚未完成图片添加,不确定代码方向是否正确,且现有资料多为旧版本内容,需要适配新版Flutter。
弃用的冗余旧代码
Container( padding: const EdgeInsets.all(8), color: const Color.fromARGB(255, 75, 175, 78), child: Center( child: TextButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const SecondPage( plantname: 'Bell Pepper'))); }, child: const Text( "Bell Pepper", style: TextStyle( fontSize: 19, fontFamily: 'RobotoMedium', color: Color(0xffeeeeee)), )), )),
待完善的初始组件代码
import 'package:flutter/material.dart'; import 'package:flutter_native_splash/cli_commands.dart'; class ListViewCard extends StatelessWidget { final String title; final void Function()? onTap; final Image imageOfPlant; const ListViewCard( {super.key, required this.title, required this.onTap, required this.imageOfPlant, }); @override Widget build(BuildContext context) { return Card( color: const Color.fromARGB(255, 75, 175, 78), elevation: 0, margin: const EdgeInsets.all(8), semanticContainer: true, clipBehavior: Clip.antiAliasWithSaveLayer, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), child: InkWell( splashColor: Colors.lightGreenAccent.withAlpha(30), onTap: onTap, //sizedBox of the card child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox( width: 150, height: 200, child: Text(title, style: const TextStyle( fontSize: 19, fontFamily: 'RobotoMedium', color: Color(0xffeeeeee)),// textstyle ),),//text //SizedBox ], // <widget>[] ), // column ), //inkwell ); // card } }
优化后的可复用带图Card组件
修改说明
- 移除无用的
flutter_native_splash/cli_commands.dart导入 - 将图片作为背景层添加,通过
Stack实现图片+文字的层级布局 - 改用
ImageProvider作为图片参数,兼容本地/网络图片场景 - 添加渐变遮罩层,提升文字在图片上的可读性
- 适当添加阴影,增强卡片层次感
- 调整文字布局,让标题固定在卡片底部
import 'package:flutter/material.dart'; class ListViewCard extends StatelessWidget { final String title; final void Function()? onTap; final ImageProvider imageOfPlant; const ListViewCard({ super.key, required this.title, required this.onTap, required this.imageOfPlant, }); @override Widget build(BuildContext context) { return Card( elevation: 4, margin: const EdgeInsets.all(8), semanticContainer: true, clipBehavior: Clip.antiAliasWithSaveLayer, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), child: InkWell( splashColor: Colors.lightGreenAccent.withAlpha(30), onTap: onTap, child: SizedBox( width: 150, height: 200, child: Stack( fit: StackFit.expand, children: [ // 卡片背景图片 Image( image: imageOfPlant, fit: BoxFit.cover, ), // 渐变遮罩层 Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withOpacity(0.6), ], ), ), ), // 标题文字 Align( alignment: Alignment.bottomLeft, child: Padding( padding: const EdgeInsets.all(12.0), child: Text( title, style: const TextStyle( fontSize: 19, fontFamily: 'RobotoMedium', color: Color(0xffeeeeee), ), ), ), ), ], ), ), ), ); } }
使用示例
// 网络图片使用 ListViewCard( title: "Bell Pepper", onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const SecondPage(plantname: 'Bell Pepper'), ), ); }, imageOfPlant: const NetworkImage("https://example.com/pepper.jpg"), ), // 本地图片使用 ListViewCard( title: "Tomato", onTap: () { /* 跳转逻辑 */ }, imageOfPlant: const AssetImage("assets/images/tomato.png"), ),
内容的提问来源于stack exchange,提问作者Giotto
相关产品推荐
相关产品推荐

