1. 安装插件
配置 flutter_html 插件。
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
date_format: ^1.0.6
flutter_cupertino_date_picker: ^1.0.26+2
flutter_swiper: ^1.1.6
fluttertoast: ^7.1.6
http: ^0.12.2
dio: ^3.0.10
# 解析HTML
flutter_html: ^1.1.0
在pubspec.yaml中配置保存后,在VS Code环境中会自动下载依赖包。
如果无法正常下载,执行 flutter pub get 。
2. 引入依赖
在需要用到的该插件的文件中引入插件包。
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/style.dart';
3. 使用插件
Html(
// 渲染的数据
data:htmlData,
// 自定义样式
style: {},
customRender: {
"flutter": (RenderContext context, Widget child, attributes, _) {
return FlutterLogo(
style: (attributes['horizontal'] != null)
? FlutterLogoStyle.horizontal
: FlutterLogoStyle.markOnly,
textColor: context.style.color,
size: context.style.fontSize.size * 5,
);
},
},
onLinkTap: (url) {
print("Opening $url...");
},
onImageTap: (src) {
print(src);
},
onImageError: (exception, stackTrace) {
print(exception);
},
),
4. 完整示例
如下所示为一个新闻列表页的代码。
// pages/News.dart;
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:dio/dio.dart';
class NewsPage extends StatefulWidget {
NewsPage({Key key}) : super(key: key);
@override
_NewsPageState createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
// 当前页数
int _page = 1;
// 页面数据
List _list = [];
// 是否还有
bool _hasMore = true;
// 滚动控制器
ScrollController _scrollController = new ScrollController();
@override
void initState() {
super.initState();
this._getData();
// 监听滚动事件
_scrollController.addListener((){
// 获取滚动条下拉的距离
// print(_scrollController.position.pixels);
// 获取整个页面的高度
// print(_scrollController.position.maxScrollExtent);
if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-40){
this._getData();
}
});
}
// 获取数据列表
void _getData() async{
if(this._hasMore){
var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=${_page}";
// 请求远程数据
Response result = await Dio().get(url);
var list = json.decode(result.data)["result"];
setState(() {
// 拼接数据
this._list.addAll(list);
this._page++;
});
if(list.length<20){
setState(() {
// 关闭加载
this._hasMore = false;
});
}
}
}
// 下拉刷新
Future<void> _onRefresh() async{
print("下拉刷新");
// 持续两秒
await Future.delayed(Duration(milliseconds:2000),(){
this._getData();
});
}
// 加载动画
Widget _getMoreWidget() {
// 如果还有数据
if(this._hasMore){
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'加载中',
style: TextStyle(fontSize: 16.0),
),
// 加载图标
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}else{
return Center(
child: Text("...我是有底线的..."),
);
}
}
@override
Widget build(BuildContext context) {
return Container(
child:Scaffold(
appBar: AppBar(
title:Text("新闻列表")
),
body:this._list.length==0?this._getMoreWidget():RefreshIndicator(
child: ListView.builder(
// 上拉加载控制器
controller: _scrollController,
itemCount: this._list.length,
itemBuilder: (context,index){
Widget tip = Text("");
// 当渲染到最后一条数据时,加载动画提示
if(index == this._list.length-1){
tip = _getMoreWidget();
}
return Column(
children: <Widget>[
ListTile(
title:Text(
"${this._list[index]["title"]}",
maxLines:1,
),
onTap:(){
Navigator.pushNamed(context,'/content',arguments: {
"aid":this._list[index]["aid"]
});
},
),
Divider(),
// 加载提示
tip
],
);
},
),
// 下拉刷新事件
onRefresh:this._onRefresh
)
)
);
}
}
新闻列表页的效果图如下:
以下是点击新闻列表页跳转详情页的代码,这个页面中会用到解析html的插件。
// pages/Content.dart;
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
// 引入解析html的插件
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/style.dart';
class ContentPage extends StatefulWidget {
final Map arguments;
ContentPage({Key key,this.arguments}) : super(key: key);
@override
_ContentPageState createState() => _ContentPageState(this.arguments);
}
class _ContentPageState extends State<ContentPage> {
final Map arguments;
List _list=[];
_ContentPageState(this.arguments);
@override
void initState() {
super.initState();
// 发起请求
this._getData();
}
// 请求数据
void _getData() async{
// 将新闻页面中传入的参数作为请求参数
var url = "http://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=${this.arguments['aid']}";
var result = await Dio().get(url);
setState(() {
this._list = json.decode(result.data)["result"];
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text("新闻详情"),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
// 官方代码
Html(
// 渲染的数据
data:this._list.length>0?this._list[0]["content"]:'',
// 自定义样式
style: {},
customRender: {
"flutter": (RenderContext context, Widget child, attributes, _) {
return FlutterLogo(
style: (attributes['horizontal'] != null)
? FlutterLogoStyle.horizontal
: FlutterLogoStyle.markOnly,
textColor: context.style.color,
size: context.style.fontSize.size * 5,
);
},
},
onLinkTap: (url) {
print("Opening $url...");
},
onImageTap: (src) {
print(src);
},
onImageError: (exception, stackTrace) {
print(exception);
},
),
],
)
),
)
);
}
}
以下是详情页解析的Html文件的效果图。