直播带货源码,flutter 顶部滚动栏+页面
直播带货源码,flutter 顶部滚动栏+页面
tabPage.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_trip/dao/travelDao.dart';
import 'package:flutter_trip/model/home/commonModel.dart';
import 'package:flutter_trip/model/travel/travelModel.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_trip/widget/applicationWebView.dart';
import 'package:flutter_trip/widget/loadingContainer.dart';
const _TRAVEL_URL =
'https://m.ctrip.com/restapi/soa2/16189/json/searchTripShootListForHomePageV2?_fxpcqlniredt=09031014111431397988&__gw_appid=99999999&__gw_ver=1.0&__gw_from=10650013707&__gw_platform=H5';
const PAGE_SIZE = 10;
class TabPage extends StatefulWidget {
final String travelUrl;
final String channelCode;
TabPage({Key? key, required this.travelUrl, required this.channelCode})
: super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _TabPageState();
}
}
class _TabPageState extends State<TabPage> with AutomaticKeepAliveClientMixin {
List<TravelItem> travelItem = [];
int pageIndex = 0;
bool isLoad = true;
ScrollController _scrollController = ScrollController();
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
@override
void initState() {
// TODO: implement initState
super.initState();
_loadData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_loadData(loadMore: true);
print("滚动到最底部有");
}
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: LoadingContainer(
isLoading: isLoad,
cover: true,
child: RefreshIndicator(
onRefresh: _handleRefresh,
child: MediaQuery.removePadding(
removeTop: true,
context: context,
child: new StaggeredGridView.countBuilder(
controller: _scrollController,
crossAxisCount: 2,
itemCount: travelItem.length,
itemBuilder: (BuildContext context, int index) =>
_TraveItem(index: index, item: travelItem[index]),
staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),
// mainAxisSpacing: 4.0,
// crossAxisSpacing: 4.0,
),
),
),
),
);
}
Future<void> _handleRefresh() async {
_loadData();
}
_loadData({bool loadMore = false}) {
if (loadMore) {
pageIndex++;
} else {
pageIndex = 0;
}
TravelDao.fetch(widget.travelUrl, widget.channelCode, pageIndex, PAGE_SIZE)
.then((value) {
setState(() {
List<TravelItem> items = _filterItems(value.resultList);
if (travelItem.length != 0) {
travelItem.addAll(items);
} else {
travelItem = items;
}
isLoad = false;
});
}).catchError((onError) {
print('网络请求出错 $onError');
});
}
List<TravelItem> _filterItems(List<TravelItem>? resultList) {
List<TravelItem> items = [];
if (resultList != null) {
resultList.forEach((element) {
if (element.article != null) {
items.add(element);
}
});
}
return items;
}
}
class _TraveItem extends StatelessWidget {
final int index;
final TravelItem item;
_TraveItem({Key? key, required this.index, required this.item})
: super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return GestureDetector(
onTap: () {
if (item.article.urls.length > 0) {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => ApplicationWebView(
// commonModel: CommonModel(
// icon: '',
// title: '详情',
// url: item.article.urls[0].h5Url,
// statusBarColor: 'ffffff',
// hideAppBar: false),
// )));
}
},
child: Card(
child: PhysicalModel(
color: Colors.transparent,
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_itemImage(),
Container(
padding: EdgeInsets.all(4),
child: Text(
item.article.articleTitle,
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 14, color: Colors.black),
),
),
_infoText(),
],
),
),
),
);
}
_itemImage() {
return Stack(
children: [
Image.network(item.article.images[0].dynamicUrl),
Positioned(
bottom: 8,
left: 8,
child: Container(
padding: EdgeInsets.fromLTRB(5, 1, 5, 1),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.location_on_outlined,
size: 12,
color: Colors.white,
),
LimitedBox(
maxWidth: 130,
child: Text(
_positonName(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, color: Colors.white),
),
)
],
),
),
)
],
);
}
String _positonName() {
// return item.article.pois?.length == 0
// ? '未知'
// : item.article.pois![0]!.poiName;
return item.article.pois?.length == 0
? '未知'
: item.article.pois![0]?.poiName ?? '未知';
}
_infoText() {
return Container(
padding: EdgeInsets.fromLTRB(6, 0, 6, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
PhysicalModel(
color: Colors.transparent,
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(12),
child: Image.network(
item.article.author!.coverImage!.dynamicUrl,
width: 24,
height: 24,
),
),
Container(
width: 90,
padding: EdgeInsets.all(5),
child: Text(
item.article.author!.nickName,
textAlign: TextAlign.left,
style: TextStyle(fontSize: 12),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.thumb_up,
color: Colors.grey,
size: 12,
),
Container(
padding: EdgeInsets.only(left: 3),
child: Text(
item.article.likeCount.toString(),
maxLines: 1,
style: TextStyle(
color: Colors.grey,
fontSize: 10,
),
),
)
],
)
],
),
);
}
}
tabTravel.dart
import 'package:flutter/material.dart';
import 'package:flutter_trip/dao/travelDao.dart';
import 'package:flutter_trip/dao/travelTabDao.dart';
import 'package:flutter_trip/model/travel/travelModel.dart';
import 'package:flutter_trip/model/travel/travelTabModel.dart';
import 'package:flutter_trip/pages/travel/tabPage.dart';
class TabTravel extends StatefulWidget {
@override
_TabTravelState createState() => _TabTravelState();
}
class _TabTravelState extends State<TabTravel>
with SingleTickerProviderStateMixin {
late TabController tabController;
late TravelTabModel travelTabModel;
bool isInit = false;
List<TravelTab> tabs = [];
@override
void initState() {
//tabController = TabController(length: 0, vsync: this);
// TODO: implement initState
super.initState();
TravelTabDao.fetch().then((TravelTabModel tabModel) {
tabController = TabController(length: tabModel.tabs.length, vsync: this);
setState(() {
tabs = tabModel.tabs;
travelTabModel = tabModel;
});
this.isInit = true;
}).catchError((error) {
print("error $error");
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Column(
children: [
isInit
? Container(
color: Colors.white,
padding:
EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: TabBar(
padding: EdgeInsets.zero,
controller: tabController,
isScrollable: true,
labelColor: Colors.black87,
labelPadding: EdgeInsets.only(left: 20, right: 20),
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Colors.lightBlue,
width: 3,
),
insets: EdgeInsets.only(bottom: 10),
),
tabs:
tabs.map((item) => Tab(text: item.labelName)).toList(),
),
)
: Container(),
Flexible(
child: isInit
? TabBarView(
controller: tabController,
children: tabs
.map((item) => TabPage(
travelUrl: travelTabModel.url,
channelCode: item.groupChannelCode))
.toList(),
// children: tabs
// .map((item) => Tab(text: item.groupChannelCode))
// .toList(),
)
: Container(),
)
],
),
);
}
@override
void dispose() {
// TODO: implement dispose
tabController.dispose();
super.dispose();
}
以上就是 直播带货源码,flutter 顶部滚动栏+页面,更多内容欢迎关注之后的文章
直播带货源码,flutter 顶部滚动栏+页面的更多相关文章
- C# 带滚动栏的Label控件
C# 带滚动栏的Label控件,用鼠标选的时候还是有点闪烁: namespace 带滚动栏的Label控件 { public class TextBoxLabel : System.Windows.F ...
- 直播带货APP源码开发为什么选择云服务器
云服务器可以为直播带货APP源码提供弹性计算以及更高的运行效率,避免资源浪费,随着直播带货APP源码业务需求的变化,可以实时扩展或缩减计算资源.CVM支持按实际使用的资源计费,可以节约计算成本. 一. ...
- Bootstrap学习笔记上(带源码)
阅读目录 排版 表单 网格系统 菜单.按钮 做好笔记方便日后查阅o(╯□╰)o bootstrap简介: ☑ 简单灵活可用于架构流行的用户界面和交互接口的html.css.javascript工具集 ...
- 自己写一个jQuery垂直滚动栏插件(panel)
html中原生的滚动栏比較难看,所以有些站点,会自己实现滚动栏,导航站点hao123在一个側栏中,就自己定义了垂直滚动栏,效果比較好看,截图例如以下: watermark/2/text/aHR0cDo ...
- [置顶]
xamarin Tablayout+Viewpager+Fragment顶部导航栏
最近几天不忙,所以把项目中的顶部导航栏的实现归集一下.android中使用TabLayout+ViewPager+Fragment制作顶部导航非常常见,代码实现也比较简单.当然我这个导航栏是基于xam ...
- 使用PagerSlidingTabStrip实现顶部导航栏
使用PagerSlidingTabStrip配合ViewPager实现顶部导航栏. 效果图如下: PagerSlidingTabStrip是github上的一个开源项目,项目地址如下 ...
- Android之仿今日头条顶部导航栏效果
随着时间的推移现在的软件要求显示的内容越来越多,所以要在小的屏幕上能够更好的显示更多的内容,首先我们会想到底部菜单栏,但是有时候像今日头条新闻客户端要显示的内容太多,而且又想在主界面全部显示出来,所以 ...
- JS 带运动的返回顶部 小案例
带运动的返回顶部:当滚动条在滚动的时候,滚动鼠标的滚轮,应该让滚动条停止滚动,清掉定时器.下面的方法b 就是清掉的方法 <!DOCTYPE html PUBLIC "-//W3C//D ...
- iOS开发项目实战——Swift实现ScrollView滚动栏功能
手机作为一个小屏设备,须要显示的信息往往无法在一个屏幕上显示,此时就须要使用到滚动栏,当然除了像TableView这样能够自带滚动功能的. 假设一个界面上View较多,那就必须要使用到ScrollVi ...
- android 滚动栏下拉反弹的效果(相似微信朋友圈)
微信朋友圈上面的图片封面,QQ空间说说上面的图片封面都有下拉反弹的效果,这些都是使用滚动栏实现的.下拉,当松开时候.反弹至原来的位置.下拉时候能看到背景图片.那么这里简介一下这样的效果的实现. 本文源 ...
随机推荐
- 滴水 1.c++类 this指针 笔记+指针
1.结构体带参数传递 将结构体的数据压入堆栈中 然后进入函数内进行处理 2.结构体指针传递 将this指针压入进去 来查找 a b数据 3.函数可以放在结构体里面,也可以放在结构体外面 放入进去后 但 ...
- LG P4980【模板】Pólya 定理
\(\text{Solution}\) \[ans = \frac{1}{n}\sum_{i=1}^n n^{(i,n)} = \frac{1}{n}\sum_{d|n}n^d\varphi(\fra ...
- JZOJ 3527.迷宫花坛(garden)
题面 思路 考场想到 \(tarjan\) 缩点 然而忘了缩点怎么打 于是甩了个暴力 改题时学了个圆方树 发现挺好用 于是······注意重边 \(Code\) #include<cstdio& ...
- 跳板攻击之:dns2tcp
跳板攻击之:dns2tcp 目录 跳板攻击之:dns2tcp 1 dns2tcp简介 2 dns2tcp 食用说明 2.1 dns2tcpd 服务端 2.1.1 服务端参数说明 2.1.2 配置文件 ...
- .net webapi+jwt demo
一.新建.net webapi程序 二.nuget包搜索jwt,点击安装 三.在model文件夹下建立三个主要类: public class AuthInfo { /// &l ...
- LeetCode算法训练-回溯总结
欢迎关注个人公众号:爱喝可可牛奶 LeetCode算法训练-回溯总结 适用问题 组合问题:N个数里面按一定规则找出k个数的集合 排列问题:N个数按一定规则全排列,有几种排列方式 切割问题:一个字符串按 ...
- EMQ X 系统调优和性能压测
前言 如果使用 EMQ 来承载百万级别的用户连接可以吗?毕竟在 MQTT 官方介绍上说 EMQ X 可以处理千万并发客户端,而 EMQ X 自己官方称 4.x 版本 MQTT 连接压力测试一台 8 核 ...
- css 属性选择器需要加引号吗
平常我们是不加引号的: HTML: <div data-a='aq1'>99</div> CSS: [data-a=aq1]{ color: #f00; } 想加上也行 ...
- 常见的git操作
git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a查看所有的分支 git branch -r 查看远程所有分支 git ...
- 下拉刷新 get请求 post请求 onLoad
"enablePullDownRefresh": true 下拉刷新之后背景颜色 "backgroundColor": "#efefef&qu ...