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

Flutter中使用html包无法展示HTML表格字符串怎么办?

解决Flutter html包无法正确渲染HTML表格的问题

问题说明

  • 预期效果:需要渲染一个规整的两列布局表格,包含员工信息、各项参数(ID、日期、地点等)以及底部的备注输入框,整体宽度占满,单元格有适配的内边距和宽度分配。
  • 实际问题:使用Flutter的html包渲染时,表格布局错乱,单元格宽度、内边距未按HTML内联样式生效,完全不符合设计要求。

需要渲染的HTML字符串:

<table id='ParametersTable' style='width:100%'>
<thead>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<label class='col-form-label'>Employee</label>
</td>
<td colspan='8' style='padding: 2px 10px 2px 10px; width: 66.66666666666666%'>1003 - Abdulsamed Demirtop</td>
</tr>
</thead>
<tbody class='parambody'>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1030' name ='1030' value='1030' hidden />
<label class='col-form-label'>Id</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>4</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1032' name ='1032' value='1032' hidden />
<label class='col-form-label'>FromDate</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>25/Dec/2022 11:30 AM</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1033' name ='1033' value='1033' hidden />
<label class='col-form-label'>EndDate</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>28/Dec/2022 11:30 PM</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1034' name ='1034' value='1034' hidden />
<label class='col-form-label'>Country</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>Turkiye</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1035' name ='1035' value='1035' hidden />
<label class='col-form-label'>City</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>Ankara</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1036' name ='1036' value='1036' hidden />
<label class='col-form-label'>Type</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>Flight</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%'>
<input id='1037' name ='1037' value='1037' hidden />
<label class='col-form-label'>Purpose</label>
</td>
<td colspan='7' style='padding: 2px 10px 2px 10px; width: 58.333333333333336%'>Meeting</td>
<td colspan='1' style='padding: 2px 0px 2px 0px; width: 8.333333333333332%'></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan='4' style='padding: 2px 10px 2px 10px; width: 33.33333333333333%; white-space: nowrap'>
<label class='col-form-label'>Notes</label>
</td>
<td colspan='8' style='padding: 2px 10px 2px 10px; width: 66.66666666666666%'>
<input id='notes' name='notes' autocomplete='off' style='width: 100%' class='form-control' />
</td>
</tr>
</tfoot>
</table>

解决方案

Flutter基础html包对复杂表格样式支持有限,尤其是colspan和内联宽度、内边距的解析容易失效,可以通过以下方式解决:

1. 更换为flutter_html增强包

flutter_html对HTML/CSS的支持更完善,能更好解析表格样式:

  • 添加依赖到pubspec.yaml:
dependencies:
  flutter_html: ^3.0.0-beta.2 # 或最新稳定版
  • 使用组件渲染:
import 'package:flutter_html/flutter_html.dart';

Html(
  data: yourHtmlString,
  style: {
    "table": Style(
      width: MediaQuery.of(context).size.width,
    ),
    "td": Style(
      padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
    ),
    "label": Style(
      fontWeight: FontWeight.bold,
    ),
  },
)

2. 简化HTML结构并补充样式

去掉冗余的colspan设置,直接用两列布局,再通过Flutter样式增强:
修改后的HTML:

<table id='ParametersTable' style='width:100%; border-collapse: collapse;'>
<thead>
<tr>
<td style='padding: 2px 10px; width: 33%; border: 1px solid #eee;'><label class='col-form-label'>Employee</label></td>
<td style='padding: 2px 10px; width: 67%; border: 1px solid #eee;'>1003 - Abdulsamed Demirtop</td>
</tr>
</thead>
<tbody class='parambody'>
<tr>
<td style='padding: 2px 10px; width: 33%; border: 1px solid #eee;'><label class='col-form-label'>Id</label></td>
<td style='padding: 2px 10px; width: 67%; border: 1px solid #eee;'>4</td>
</tr>
<!-- 其他行按此格式修改 -->
<tr>
<td style='padding: 2px 10px; width: 33%; border: 1px solid #eee;'><label class='col-form-label'>Notes</label></td>
<td style='padding: 2px 10px; width: 67%; border: 1px solid #eee;'><input id='notes' name='notes' autocomplete='off' style='width: 100%' class='form-control' /></td>
</tr>
</tbody>
</table>

用基础html包渲染时包裹在容器中:

import 'package:flutter/material.dart';
import 'package:html/parser.dart' show parse;
import 'package:html/dom.dart' as dom;

Widget buildHtmlTable(String html) {
  return Container(
    width: double.infinity,
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: HtmlWidget(
      html,
      webView: false,
      textStyle: TextStyle(fontSize: 14),
    ),
  );
}

3. 手动解析HTML构建原生Table

如果对样式要求极高,直接用Flutter原生Table组件构建:

import 'package:flutter/material.dart';
import 'package:html/parser.dart' show parse;

Widget buildNativeTable(String html, BuildContext context) {
  final document = parse(html);
  final table = document.querySelector('#ParametersTable');
  
  List<TableRow> rows = [];
  
  // 处理表头
  final theadTr = table.querySelector('thead tr');
  final thCells = theadTr.querySelectorAll('td');
  rows.add(TableRow(
    children: [
      Padding(
        padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
        child: Text(thCells[0].text, style: TextStyle(fontWeight: FontWeight.bold)),
      ),
      Padding(
        padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
        child: Text(thCells[1].text),
      ),
    ],
  ));
  
  // 处理表体
  final tbodyTrs = table.querySelectorAll('tbody tr');
  for(var tr in tbodyTrs) {
    final cells = tr.querySelectorAll('td');
    rows.add(TableRow(
      children: [
        Padding(
          padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
          child: Text(cells[0].querySelector('label').text, style: TextStyle(fontWeight: FontWeight.bold)),
        ),
        Padding(
          padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
          child: Text(cells[1].text),
        ),
      ],
    ));
  }
  
  // 处理表尾
  final tfootTr = table.querySelector('tfoot tr');
  final tfootCells = tfootTr.querySelectorAll('td');
  rows.add(TableRow(
    children: [
      Padding(
        padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
        child: Text(tfootCells[0].text, style: TextStyle(fontWeight: FontWeight.bold)),
      ),
      Padding(
        padding: EdgeInsets.symmetric(horizontal:10, vertical:2),
        child: TextField(
          decoration: InputDecoration(border: OutlineInputBorder()),
        ),
      ),
    ],
  ));
  
  return Table(
    border: TableBorder.all(color: Colors.grey.shade200),
    columnWidths: {
      0: FixedColumnWidth(MediaQuery.of(context).size.width * 0.33),
      1: FlexColumnWidth(),
    },
    children: rows,
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:46:07