Flutter自定义按钮实现求助:复刻Figma设计的首页按钮
实现Figma设计的带SVG图标按钮
1. 添加SVG支持依赖
首先在pubspec.yaml中添加flutter_svg依赖以加载SVG图标:
dependencies: flutter: sdk: flutter flutter_svg: ^2.0.9 # 使用最新版本即可
执行flutter pub get完成依赖安装。
2. 配置SVG资源
将SVG图标文件放入项目assets/icons/目录(例如命名为reminder_icon.svg、news_icon.svg、recipe_icon.svg),然后在pubspec.yaml中声明资源:
flutter: assets: - assets/icons/
3. 自定义带图标的按钮组件
创建可复用的IconTextButton组件,实现图标在上、文字在下的布局,同时复刻设计中的圆角、阴影样式:
import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class IconTextButton extends StatelessWidget { final String svgPath; final String buttonText; final VoidCallback onPressed; final Color? backgroundColor; final Color? textColor; const IconTextButton({ super.key, required this.svgPath, required this.buttonText, required this.onPressed, this.backgroundColor = Colors.white, this.textColor = Colors.black87, }); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: backgroundColor, foregroundColor: textColor, elevation: 4, // 匹配设计的阴影高度 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), // 圆角大小 ), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), minimumSize: const Size(100, 80), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ SvgPicture.asset( svgPath, width: 40, height: 40, colorFilter: ColorFilter.mode(textColor!, BlendMode.srcIn), ), const SizedBox(height: 8), Text( buttonText, textAlign: TextAlign.center, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), ), ], ), ); } }
4. 替换原有按钮为自定义组件
修改HomePage代码,用IconTextButton替代普通ElevatedButton,同时优化布局适配:
import 'package:flutter/material.dart'; import 'package:medreminder/NewsArticle/news_home.dart'; import 'package:medreminder/Reminder/ui/home_reminder.dart'; void main() { runApp(const HomePage()); } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: const Text('Medicine Reminder App'), ), body: Column( children: [ Image.asset( 'images/MenuImg.jpg', width: double.infinity, // 适配屏幕宽度 height: 200, fit: BoxFit.cover, ), const SizedBox(height: 20.0), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ Expanded( child: IconTextButton( svgPath: 'assets/icons/reminder_icon.svg', buttonText: 'Reminder', onPressed: () { Navigator.of(context, rootNavigator: true).push( MaterialPageRoute(builder: (context) => const ReminderHomePage()), ); }, ), ), const SizedBox(width: 16), Expanded( child: IconTextButton( svgPath: 'assets/icons/news_icon.svg', buttonText: 'News & Article', onPressed: () { Navigator.of(context, rootNavigator: true).push( MaterialPageRoute(builder: (context) => const NewsHomePage()), ); }, ), ), const SizedBox(width: 16), Expanded( child: IconTextButton( svgPath: 'assets/icons/recipe_icon.svg', buttonText: 'Healty Food Recipe', onPressed: () {}, ), ), ], ), ), ], ), ), ); } }
额外优化说明
- 将顶部图片宽度设为
double.infinity,避免固定宽度导致的适配问题 - 用
Expanded包裹按钮,让三个按钮在屏幕上均匀分配宽度 - 增加左右内边距,避免按钮贴边影响视觉效果
内容的提问来源于stack exchange,提问作者NyK
相关产品推荐
相关产品推荐

