本项目借用 逛丢 网站的部分数据,仅作为 flutter 开发学习之用。 逛丢官方网址:https://guangdiu.com/
flutter 项目实战三 json数据解析以及Gson格式化flutter 项目实战二 网络请求
flutter 项目实战五 item 点击跳转,webview加载
flutter 项目实战七 bottomNavigationBar
在上一部分完成了列表数据的展示,我们可以将item的数据抽出来作为一个单独的widget ,这样在其他的地方我们也直接可以引用了。
新建 index_item.dart
class IndexItem extends StatelessWidget{
RstData rstData;
IndexItem({this.rstData}):assert(rstData!=null);//参数rstData必填且不为空
@override
Widget build(BuildContext context) {
// TODO: implement build
return _listItem(this.rstData);
}
//list列表的item
Widget _listItem(RstData rstdata){
return Container(
height: 110,//设置item的高度
margin: EdgeInsets.only(left: 5,right: 5,top: 5),//设置item的边距
decoration: BoxDecoration(
border: Border.all(color: Colors.black54,width: 1),//设置边框的宽度 以及 颜色
borderRadius: BorderRadius.all(Radius.circular(5)),//设置圆角
),
child: Row(
children: <Widget>[
Container(
height: 100,
margin: EdgeInsets.all(5),//设置图片的边距
child: Image.network(rstdata.image),
),//涉及到widget的大小或者边框的时候,使用container包裹
Expanded(
child: Container(
margin: EdgeInsets.only(right: 5),
child: Column(
children: <Widget>[
Text(rstdata.title),
Expanded( //此处使用expanded 填充,然后设置container 的对其方式确保 在底部显示
child: Row(
children: <Widget>[
Container(
alignment: Alignment.bottomLeft,//设置container的对其方式
child: Text(rstdata.mall,style: TextStyle(color: Colors.green[500]),),
),
Expanded(
child: Container(
alignment: Alignment.bottomRight,//设置container的对其方式
child: Row(
mainAxisAlignment: MainAxisAlignment.end,//设置ROW的对其显示方式
children: <Widget>[
Text("${rstdata.pubtime}-",style: TextStyle(color: Colors.green[500],fontSize: 10),),
Text(rstdata.fromsite,style: TextStyle(color: Colors.green[500],fontSize: 10),),
],
),
),
),
],
),
),//expanded类似于Android View的layout_weight属性按照比例填充,flex: 为1 时可以不填写此属性
],
),
),
),
],
),
);
}
}
修改 home_index.dart的 _listInfos() 方法,因为对于每一个item都要添加点击事件,但是container不提供点击事件,所有需要把每一个的item包裹一个支持点击事件的widget,此处我们使用 GestureDetector() ,GestureDetector支持各种触摸事件:
代码修改为:
//list列表
Widget _listInfos(){
return ListView.builder(
itemCount: _listData==null?0:_listData.length,
itemBuilder: (content,index){
RstData data=_listData[index];
return GestureDetector(
child: IndexItem(rstData: data,),
onTap: (){
_itemClick(data);
},
);
}
);
}
由于 逛丢的item详情是html页面,所以需要使用webview来加载。flutter 本身不提供 webview 所有此处我们需要导入插件flutter_webview_plugin,在 pubspec.yaml 中添加 flutter_webview_plugin: ^0.2.1+2
然后编写详情加载页:
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
class ItemInfoDetail extends StatefulWidget{
int id;
String title;
ItemInfoDetail({this.id,this.title});
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return InfoDetail(id: id,title: title);
}
}
class InfoDetail extends State<ItemInfoDetail>{
int id;
String title;
String url="https://guangdiu.com/api/showdetail.php";
InfoDetail({this.id,this.title});
@override
Widget build(BuildContext context) {
// TODO: implement build
return WebviewScaffold(
appBar: AppBar(
title: Text(title),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios,color: Colors.white,),
onPressed: (){
Navigator.pop(context);
}),
),
url: "$url?id=$id&btn=1&kepler=1&bc=1",
withJavascript: true,
withLocalStorage: true,
withZoom: false,
);
}
}
_itemClick(data);
中的代码
void _itemClick(RstData data){
Navigator.push(context, MaterialPageRoute(builder: (cx)=>ItemInfoDetail(id: data.id,title: data.title,)));
}
这是写就直接可以加载详情页了,其中 Navigator.push 与 Navigator.pop 为页面间跳转的代码,Navigator.push 类似Android的 startActivity ,Navigator.pop 相当于 finish ,如果返回时需要带参数,可以直接写成 Navigator.pop(context,"参数一",参数二,.....),相比较于 react native 的路由跳转,这是相当的方便了。
上面的内容只是加载了网页,但是在实际使用的时候可能会出现各种各样的问题,所以我们还得给webview的加载加上监听,来监听状态的变化以及添加加载错误时的操作。
修改代码为
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
class ItemInfoDetail extends StatefulWidget{
int id;
String title;
ItemInfoDetail({this.id,this.title});
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return InfoDetail(id: id,title: title);
}
}
class InfoDetail extends State<ItemInfoDetail>{
int id;
String title;
String url="https://guangdiu.com/api/showdetail.php";
InfoDetail({this.id,this.title});
FlutterWebviewPlugin flutterWebviewPlugin=FlutterWebviewPlugin();
StreamSubscription<String> _urlchange;
@override
void initState() {
// TODO: implement initState
super.initState();
_urlchange=flutterWebviewPlugin.onUrlChanged.listen((loadUrl){
//WebviewScaffold 加载的url变化时触发此方法
print(loadUrl);
});
//加载错误时监听
flutterWebviewPlugin.onHttpError.listen((error){
print(error.code);
});
//加载状态变化监听
flutterWebviewPlugin.onStateChanged.listen((state){
print(state.type.toString());
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return WebviewScaffold(
appBar: AppBar(
title: Text(title),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios,color: Colors.white,),
onPressed: (){
Navigator.pop(context);
}),
),
url: "$url?id=$id&btn=1&kepler=1&bc=1",
withJavascript: true,
withLocalStorage: true,
withZoom: false,
);
}
}
码云 git 下载
kotlin版本的源码下载:git下载地址