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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:45:06