Flutter自定义发票Widget开发求助:新手寻求技术指导
Flutter 发票Widget实现方案
针对你需要的发票样式,这里提供一个结构化的实现思路和代码示例,不用单纯依赖Container,而是组合Flutter基础组件来构建:
核心结构拆分
发票通常可拆分为以下模块,逐个实现后再组合:
- 顶部标题与商家信息区
- 商品项目列表区(含表头)
- 金额合计区
- 底部备注区
完整代码示例
import 'package:flutter/material.dart'; class InvoiceWidget extends StatelessWidget { const InvoiceWidget({super.key}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 顶部标题与商家信息 const Text( "INVOICE", style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), const Text( "ABC Store", style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, ), ), const Text("123 Business Street, City"), const Text("Phone: (123) 456-7890 | Email: support@abcstore.com"), const SizedBox(height: 24), const Divider(thickness: 1), const SizedBox(height: 16), // 商品列表表头 Row( children: const [ Expanded(flex: 3, child: Text("ITEM", style: TextStyle(fontWeight: FontWeight.bold))), Expanded(child: Text("QTY", style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)), Expanded(child: Text("PRICE", style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.right)), Expanded(child: Text("TOTAL", style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.right)), ], ), const SizedBox(height: 8), const Divider(thickness: 0.5), // 商品列表项 _buildInvoiceItem("Wireless Headphones", 1, 99.99, 99.99), _buildInvoiceItem("Screen Protector", 2, 14.99, 29.98), _buildInvoiceItem("Phone Case", 1, 24.99, 24.99), const SizedBox(height: 16), const Divider(thickness: 1), const SizedBox(height: 16), // 金额合计 Align( alignment: Alignment.centerRight, child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ const Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text("Subtotal: "), Text("\$154.96", style: TextStyle(fontWeight: FontWeight.w600)), ], ), const SizedBox(height: 8), const Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text("Tax (10%): "), Text("\$15.50", style: TextStyle(fontWeight: FontWeight.w600)), ], ), const SizedBox(height: 8), const Divider(thickness: 0.5, indent: 60), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.end, children: const [ Text("Total: ", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), Text("\$170.46", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), ], ), ], ), ), const SizedBox(height: 24), const Divider(thickness: 1), const SizedBox(height: 16), // 底部备注 const Text("Thank you for your business!", style: TextStyle(fontStyle: FontStyle.italic)), const Text("Payment due within 30 days"), ], ), ), ), ); } Widget _buildInvoiceItem(String itemName, int qty, double price, double total) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ Expanded(flex: 3, child: Text(itemName)), Expanded(child: Text(qty.toString(), textAlign: TextAlign.center)), Expanded(child: Text("\$$price", textAlign: TextAlign.right)), Expanded(child: Text("\$$total", textAlign: TextAlign.right)), ], ), ); } }
关键实现说明
- 用
Padding统一控制内边距,避免直接在Container硬写间距 Row+Expanded实现横向等比布局,确保商品项与表头对齐Divider分隔不同区域,增强视觉层次- 提取
_buildInvoiceItem方法复用列表项代码,减少冗余 - 外层Container添加边框和圆角,模拟发票纸质质感
你可以根据实际需求调整字体大小、颜色、间距,或添加日期、发票编号等字段。如果需要适配不同屏幕,还可使用LayoutBuilder动态调整布局。
内容的提问来源于stack exchange,提问作者Zulfi Achsan Sani
相关产品推荐
相关产品推荐

