本项目借用 逛丢 网站的部分数据,仅作为 flutter 开发学习之用。 逛丢官方网址:https://guangdiu.com/
flutter 项目实战三 json数据解析以及Gson格式化flutter 项目实战二 网络请求
flutter 项目实战五 item 点击跳转,webview加载
flutter 项目实战七 bottomNavigationBar
海淘的页面与首页相似,仅是数据请求来源有区别,不再此处多做赘述,直接给一个效果图吧!
下面开始小时风云榜的内容。
首先对界面的结构进行分析,先上效果图:
开始分析
整个页面可以分为二个区域,appbar与内容展示区,内容展示区域也可以分为两个部分,列表展示区以及时间控制区,根据涉及,当时间控制区的上一小时以及下一小时点击时appbar的title会按照展示的时间变化。
接下来开始分析列表的每个 item
item的最外层是一个竖向排列的column ,分为内容区与分割线,内容区是一个Row,左边一个图片加图标,右边又是一个column,上部text,下部分是一个Row,靠左显示的一个。
下面开始码代码了。突然不想一部分一部分写了,还是先直接上完整的代码吧!
还是上代码吧!懒点吧,毕竟代码还是自己写的,代码来了:
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'table/resp_result.dart';
import 'util/http_util.dart';
import 'ItemInfoDetail.dart';
class HourRank extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return HourWidget();
}
}
class HourWidget extends State<HourRank>{
int hour=0;
int currentHour=0;
String title="小时风云榜";
List<RstData> listdata;
String day;
bool getData=false;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(title,style: TextStyle(color: Colors.white),),
backgroundColor: Color.fromARGB(255, 0, 175, 0),
),
body: _content(),
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
_getCurrentTime();
hour=currentHour;
_changeTitle(hour);
_getServerData();
}
//获取当前时间
void _getCurrentTime(){
DateTime time=DateTime.now();
currentHour=time.hour;
var m=time.month>=10?"${time.month}":"0${time.month}";
var d=time.day>=10?"${time.day}":"0${time.day}";
day="${time.year}$m$d";
print(time.toString());
}
void _changeTitle(int hour){
setState(() {
title="小时风云榜 - 今日$hour时榜";
});
}
void _getServerData(){
HttpUtil().get("getranklist.php?date=$day&hour=$hour").then((resp){
var data=RespResult.fromJson(resp.data);
setState(() {
listdata=data.data;
getData=true;
});
});
}
Widget _content(){
return Stack(
children: <Widget>[
_hoursConent(),
Container(
alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(bottom: 10, right: 50, left: 50),
child: Container(
height: 40,
decoration: BoxDecoration(
border: Border.all(color: Colors.black54),
borderRadius: BorderRadius.all(Radius.circular(25)),
color: Colors.white
),
child: Row(
children: <Widget>[
Expanded(
child: GestureDetector(
child: _lastHour(),
onTap: () {
_onLastHour();
},
),
),
Container(
width: 1,
color: Colors.black54,
),
Expanded(
child: GestureDetector(
child: _nextHour(),
onTap: () {
_onNextHour();
},
),
),
],
),
),
)
],
);
}
//圆形进度条
Widget _loadingProgress(){
return Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 3.0,
valueColor: AlwaysStoppedAnimation<Color>(Color.fromARGB(255, 0, 175, 0)),
),
),
Container(
margin: EdgeInsets.only(left: 20),
child: Text("正在加载数据..."),
),
],
),
);
}
//小时列表数据或者进度条
Widget _hoursConent(){
if(getData){
return ListView.builder(
itemCount: listdata == null ? 0 : listdata.length,
itemBuilder: (content, index) {
return _contentIten(listdata[index], index);
}
);
}else{
return _loadingProgress();
}
}
//上一小时
Widget _lastHour(){
if(hour>0){
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.arrow_back_ios,
color: Color.fromARGB(255, 0, 175, 0), size: 20,),
Text("上一小时",style: TextStyle(color: Color.fromARGB(255, 0, 175, 0)),)
],
);
}else{
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.arrow_back_ios,
color: Colors.grey, size: 20,),
Text("上一小时",style: TextStyle(color: Colors.grey),)
],
);
}
}
//下一小时
Widget _nextHour(){
if(hour==currentHour) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("下一小时",style: TextStyle(color: Colors.grey),),
Icon(Icons.arrow_forward_ios,
color: Colors.grey),
],
);
}else{
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("下一小时",style: TextStyle(color: Color.fromARGB(255, 0, 175, 0))),
Icon(Icons.arrow_forward_ios,
color: Color.fromARGB(255, 0, 175, 0),),
],
);
}
}
//单个列表项
Widget _contentIten(RstData data,int index){
return Column(
children: <Widget>[
SizedBox(
child: GestureDetector(
child: Container(
height: 110,
child: Row(
children: <Widget>[
Container(
width: 110,
height: 110,
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.all(5),
child: Image.network(data.image),
),
Container(
alignment: Alignment.topLeft,//CD919E
height: 20,
width: 50,
color: Color.fromARGB(255, 205, 145, 158),
child: Center(
child: Text("No.${index+1}",style: TextStyle(color: Colors.white),),
),
)
],
),
),
Expanded(
child: Column(
children: <Widget>[
Container(
color: Colors.white,
alignment: Alignment.topLeft,
child: Text(data.title),
),
Expanded(
child: Container(
child: Row(
children: <Widget>[
Container(
color: Colors.white,
alignment: Alignment.bottomLeft,
child: Text(data.mall,style: TextStyle(color: Color.fromARGB(255, 0, 175, 0)),),
),
Expanded(
child: Container(
color: Colors.white,
alignment: Alignment.bottomRight,
child: Text(data.pubtime,style: TextStyle(color: Color.fromARGB(255, 0, 175, 0)),),
),
)
],
),
),
),
],
),
),
],
),
),
onTap: (){_itemClick(data);},
),
),
Container(
height: 1,
decoration: BoxDecoration(
border: Border.all(color: Colors.black54)
),
),
],
);
}
//列表item点击事件
void _itemClick(RstData data){
Navigator.push(context, MaterialPageRoute(builder: (context)=>InfoDetail(id:data.id,title: data.title,)));
}
void _onLastHour(){
if(hour>0) {
setState(() {
getData=false;
});
hour--;
_changeTitle(hour);
_getCurrentTime();
_getServerData();
}else{
// Toast.toast(context, "仅展示当天的小时风云榜");
}
}
void _onNextHour(){
_getCurrentTime();
if(hour<currentHour){
setState(() {
getData=false;
});
hour++;
_changeTitle(hour);
_getServerData();
}else{
// Toast.toast(context, "已是最新数据");
}
}
}
之所以把其中的toast屏蔽掉是因为我忘了这个是我才什么地方参考来的了,所以先不加了,到时候放在源码里面。
上一张实现的效果图:
与kotlin实现的界面略有不同,不用在意这些。先说明一下代码里面出现的知识点把!
首先是时间的获取 DateTime time=DateTime.now(); 是获取当前时间,可以获取年月日时分秒毫秒值等。
布局widget 上我们用到了 Stack ,Stack与relatelayout 类似,item的左侧的标签与图片的布局就是使用stack实现的。
到此项目基本上就结束了,如有添加,我再来增补内容。
最后不能把源码给忘了
码云 git 下载
kotlin版本的源码下载:git下载地址