这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
废话开篇:对于网页中超出父级标签部分的展示方式大家应该很熟悉,可以设置为滚动、切除等,但是在flutter开发中就遇到了这样的一个难题,table标签的宽度大于屏幕宽度,这样的情况下,flutter会UI超限警告,真的是搞了一天,还是自己太年轻,下面简单记录一下之间摸索的方法及误区。
话不多说,大家先看报错截图:
由于table表格的最小宽度还是超过了屏幕,这里也是黄牌警告了。
正确的解决方式
这里是html组件的全部内容,大家要注意的是里面有个 customRender 参数,这里就是传对于html标签的通用渲染方式,意思就是在渲染table标签的时候需要单独进行渲染,在代码中添加一个 SingleChildScrollView 横向滚动的组件,实现超过屏幕部分的table可以以滚动的方式浏览全部,这样也就满足了布局要求,去掉了黄牌警告。
child: new Container(
padding: EdgeInsets.only(left: 0,right: 10),
child: new Html(
shrinkWrap: false,
data: detailArticle != null ? detailArticle!.content + '<p style="font-size:11px">阅读量:'+ detailArticle!.readNum.toString() + '</p>' : '',
style: {
'*':Style(color: Colors.black,letterSpacing: 3,lineHeight: LineHeight(1.7),fontFamily: "SY",fontSize:FontSize(16) ,fontWeight: FontWeight.w500),
},
customRender: {
"table": (context, child) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:
(context.tree as TableLayoutElement).toWidget(context),
);
},
},
// navigationDelegateForIframe: navigationDelegate,
),
),
上面的代码其实真的是没有想到 flutter 还可以这样秀。
接下来说一下解决问题中走过的弯路。
弯路 一
单独给组件 html 添加水平滚动方向的 SingleChildScrollView 。无效,html 组件的宽度是不会改变的,所以添加水平滚动组件实际是没有意义的。
弯路 二
解析后台返回的网页标签,修改 table 标签的属性。无效,无论是在全局加上css样式并添加最高权重还是逐一标签解析直接修改 table 标签的属性都是徒劳的,这里展示一下解析的一些操作代码。
//引入 dom 库
import 'package:html/dom.dart' as DOM;
先简单的描述一下解析意图:递归式解析所有标签,找到 table 标签,修改 table 标签的 attributes 下 style 的相关属性(文字可以折行、宽度最大100%)或者在 table 标签 外层嵌套一层 div 标签并设置其 style 的overfloat 属性为 scroll,结果可想而知,都是无效的。不过也总结了一些flutter 对 dom 解析的一些知识细节。
代码仅供交流,代码拙劣,不敢弄斧。
//解析网页demo
static void parseSpecialElement(DOM.Element element,DOM.Element tempElement){
for(int i = 0;i < element.children.length;i++){
DOM.Element childElement = element.children[i];
DOM.Element nextElement = new DOM.Element.tag(childElement.localName);
if(childElement.localName.toString() == 'table') {
//EventBusUtils.getInstance().fire(new WSlArticleWidthNeedChange(isNeedChangeWidth: true));
DOM.Element divElement = new DOM.Element.tag('div');
LinkedHashMap<Object, String> divAttributes = new LinkedHashMap();
divAttributes['style'] = 'width: 100px;height: 300px;background-color: red;';
divElement.attributes = divAttributes;
LinkedHashMap<Object, String> newAttributes = new LinkedHashMap();
newAttributes['style'] = 'white-space:normal;width: 100%;table-layout: fixed; word-break: break-all;';
nextElement.attributes = newAttributes;
if(childElement.children.length == 0){
nextElement.text = childElement.text;
} else {
parseSpecialElement(childElement,nextElement);
}
divElement.append(nextElement);
tempElement.append(divElement);
//debugPrint(childElement.attributes.toString());
} else if(childElement.localName.toString() == 'td') {
LinkedHashMap<Object, String> newAttributes = new LinkedHashMap();
newAttributes['style'] = 'white-space:normal;word-break: break-all;';
nextElement.attributes = newAttributes;
if(childElement.children.length == 0){
nextElement.text = childElement.text;
} else {
parseSpecialElement(childElement,nextElement);
}
tempElement.append(nextElement);
} else {
if(childElement.children.length == 0){
//debugPrint('childElement = ' + childElement.outerHtml);
nextElement.text = childElement.text;
} else {
parseSpecialElement(childElement,nextElement);
}
nextElement.attributes = childElement.attributes;
tempElement.append(nextElement);
}
}
}
下面展示一下正常查看 table 标签过宽时候的方式。
没有什么特别难的技术,只是遇到问题写下来,真是绕了一大圈弯路,错误的路不代表它会指导你成功,但它至少会告诉你它为你找到正确的方向提供了一次借鉴,记录一下,代码拙劣,大神勿喷,如果对大家有帮助,更是深感欣慰。