赞
踩
使用 :RefreshIndicator+NestedScrollView+(TabBar、TabView)+SmartRefresher打造可下拉刷新和上拉加载的tab吸顶效果。
上拉吸顶
1.导入
pull_to_refresh: ^2.0.0
flutter_swiper: ^1.1.6
2.RefreshIndicator+NestedScrollView
class ListPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ListPageState();
}
class _ListPageState extends State<ListPage>
with AutomaticKeepAliveClientMixin ,TickerProviderStateMixin{
/// 轮播图
List<BannerModel> bannerList = [];
SwiperController _swiperController;
List<GoodsListModel> goodsList = [];
int pageNum = 1;
int _position = 0;
List<GoodsCategoryBean> _goodsCategoryList = [];
TabController _tabController;
bool _isFirstIn = true;
@override
void initState() {
super.initState();
_swiperController = SwiperController();
_swiperController.startAutoplay();
if(_isFirstIn){
_isFirstIn = false;
}
getData();
}
@override
void dispose() {
_swiperController.stopAutoplay();
_swiperController.dispose();
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back_ios),
),
iconTheme: IconThemeData(color: Color(0xff999999)),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(),
Container(
margin: EdgeInsets.only(right: setWidth(34)),
child: Text(
S.current.remenshangpin,
style: TextStyle(color: Colors.black),
),
),
GestureDetector(
onTap: () {
esLoadingToast('去搜索');
},
child: Image.asset(
PathConfig.imageSearch,
fit: BoxFit.cover,
width: 40.w,
height: 40.w,
color: HexColor('#999999'),
),
)
],
),
centerTitle: true,
),
body: RefreshIndicator(
notificationPredicate: (notifation) {
// 返回true即可,避免下拉刷新时和NestedScrollView滑动冲突
return true;
},
child:NestedScrollView(
headerSliverBuilder: (BuildContext context,bool b){
return [initSliverPersistentHeader(),initSliverPersistentHeaderTwo()];
},
body: _goodsListView(),
), onRefresh: (){
pageNum = 1;
getData();
return Future.value(true);
},
),
);
}
//轮播
_swiperView(){
return Container(
child: Swiper(
itemCount: bannerList?.length ?? 0,
loop: false,
autoplay: false,
controller: _swiperController,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
BannerModel banner = bannerList[index];
if (banner.inner) {
if (banner.itemType == 1) {
NavigatorUtil.push(GoodsDetail(
goodsId: '${banner.itemId}',
));
} else if (banner.itemType == 4) {
VideoUtil.viewVideoDetail(context, banner.itemId);
} else if (banner.itemType == 2) {
CinemaUtil.viewCinemaDetail(
context, banner.itemId, null);
} else if (banner.itemType == 3) {
NavigatorUtil.push(LifeServiceDetail(
itemId: int.parse('${banner.itemId}'),
));
}
} else {
NavigatorUtil.push(
ViewMain(url: banner.redirectLink));
}
},
child: CachedNetworkImage(
imageUrl: bannerList[index].banner,
fit: BoxFit.fill,
));
},
pagination: SwiperPagination(
builder: DotSwiperPaginationBuilder(
color: Colors.white.withAlpha(80),
activeColor: Colors.white),
),
),
);
}
//商品类别tab
_goodsTabBar() {
if(_goodsCategoryList.isNotEmpty){
return TabBar(
controller: _tabController,
// tabs的长度超出屏幕宽度后,TabBar,是否可滚动
isScrollable: true,
// 设置tab文字的类型
labelStyle: TextStyle(
fontSize: 15, letterSpacing: 1, fontWeight: FontWeight.w600),
// 设置tab选中得颜色
labelColor: JadeColors().claret,
// 设置tab未选中的颜色
unselectedLabelColor: JadeColors().grey,
// 设置tab未选中时文字的类型
unselectedLabelStyle: TextStyle(fontSize: 15, letterSpacing: 1),
indicatorWeight: 0.01,
indicatorColor: Colors.transparent,
tabs: _goodsCategoryList
.map((value) => Tab(
text: value.name,
)).toList(),
);
}else{
return Container();
}
}
_goodsListView() {
if(_goodsCategoryList.isNotEmpty){
return TabBarView(
controller: _tabController,
children: _tabViews(),
);
}else{
return Container();
}
}
_tabViews(){
List<Widget> _tabViewList = [];
for(int i = 0;i<_goodsCategoryList.length;i++){
_tabViewList.add(GoodsListPage(categoryParams: _goodsCategoryList[i],index: i,key: Key('$i'),));//传入类别数组的index,
}
return _tabViewList;
}
void getData() {
Future.delayed(Duration(seconds: 1), () {
// 接口请求
1.banner请求
2.tabBar数据请求
_httpGoodsCategory();
});
}
//商品类别
_httpGoodsCategory(){
HttpApplication.getInstance().goodsCategoryList(callBack: (result){
if(result!=null){
if(mounted){
List<GoodsCategoryBean> _dataList = [];
for(int i = 0; i< result.length; i++){
GoodsCategoryBean _goodsCategoryBean = GoodsCategoryBean.fromJson(result[i]);
if(_goodsCategoryBean.parentId == 0){
_dataList.add(_goodsCategoryBean);
}
}
_goodsCategoryList = _dataList;
if(_goodsCategoryList.isNotEmpty){
_tabController = TabController(length: _goodsCategoryList.length, vsync: this);
_tabController.addListener(() {
_position = _tabController.index;
});
_tabController.index = _position; //保持刷新时,tabBar index不会置为0
}
if(!_isFirstIn){
ATuiEventBusTool.shared().fire({"type":"reset_page_num","viewIndex": _position});
}
}
setState(() {});
}
},errorCallBack: (error){
setState(() {});
});
}
initSliverPersistentHeader() {
return SliverPersistentHeader(
//是否固定头布局 默认false
pinned: false,
//是否浮动 默认false
floating: false,
//必传参数,头布局内容
delegate: MySliverDelegate(
//缩小后的布局高度
minHeight: 40.0,
//展开后的高度
maxHeight: Utils().screenWidth(context) * 0.6,
child: Container(
color: Colors.white,
child: _swiperView()),
));
}
initSliverPersistentHeaderTwo() {
return SliverPersistentHeader(
//是否固定头布局 默认false
pinned: true,
//是否浮动 默认false
floating: false,
//必传参数,头布局内容
delegate: MySliverDelegate(
//缩小后的布局高度
minHeight: 56.0,
//展开后的高度
maxHeight: 56.0,
child: Container(
color: Colors.white,
child: _goodsTabBar()),
));
}
@override
bool get wantKeepAlive => true;
}
class MySliverDelegate extends SliverPersistentHeaderDelegate {
MySliverDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double minHeight; //最小高度
final double maxHeight; //最大高度
final Widget child; //子Widget布局
@override
double get minExtent => minHeight;
@override
double get maxExtent => max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override //是否需要重建
bool shouldRebuild(MySliverDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
2.tabView中子页面GoodsListPage
class GoodsListPage extends StatefulWidget{
final GoodsCategoryBean categoryParams;
final physics;
final index;
final Key key;
GoodsListPage({this.categoryParams,this.physics,this.index,this.key}):super(key:key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _GoodsListPage();
}
}
class _GoodsListPage extends State<GoodsListPage>{
List<GoodsListModel> _goodsList = [];
int _page = 1;
int _pageSize = 20;
int _viewIndex = 0;
var _loadType;
RefreshController refreshController;
@override
void initState() {
// TODO: implement initState
super.initState();
refreshController = RefreshController();
_refreshHttp();
//判断创建时传入的index,是否和通过EvenBus通知过来的tabController.index相等
//相等则请求接口(只让当前页请求接口,防止每个子页面都请求)
ATuiEventBusTool.shared().on().listen((event) {
_viewIndex = event["viewIndex"];
_loadType = event["type"];
if(_loadType=="reset_page_num" && _viewIndex ==widget.index){
_refreshHttp();
}
});
}
@override
Widget build(BuildContext context) {
return SmartRefresher(
footer: defaultRefreshFooter(),
controller:refreshController,
enablePullDown: false,//禁止下拉刷新,防止与主页面冲突
enablePullUp: true,
onLoading: ()async{
_loadMoreHttp();
},
child: CustomizeStaggeredGridView.countBuilder(
crossAxisCount: 4,
staggeredTileBuilder: (int index) => StaggeredTile.fit(2),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
itemCount: math.max(0, _goodsList.length * 2 - 1),
shrinkWrap: true,
//physics: physics,
itemBuilder: (_, index) {
GoodsListModel info = _goodsList[index];
return GoodsItem(
index: index,
item: info,
);
},
separatorBuilder: (_, __) => Container(),
),
);
}
_httpGoodsList(){
var params = {
"goodsCategoryParentId": widget.categoryParams.id,
"pageNum": _page,
"pageSize": _pageSize, //默认20条
"sort": 1
};
HttpApplication.getInstance().goodsList(params,callBack: (result){
if(result != null){
if(mounted){
List<GoodsListModel> _resultList = [];
var dataList = result['list'];
for(int i = 0; i< dataList.length; i++){
GoodsListModel _goodsListModel = GoodsListModel.fromJson(dataList[i]);
_resultList.add(_goodsListModel);
}
if(_page == 1){
_goodsList = _resultList;
setState(() {});
}else{
_goodsList.addAll(_resultList);
setState(() {});
Future.delayed(Duration(microseconds: 500),(){
if(_resultList.length < _pageSize){
//没有更多数据
if (refreshController.isLoading) {
refreshController.loadNoData();
}
}else{
if (refreshController.isLoading) {
refreshController.loadComplete();
}
}
});
}
}
}
},errorCallBack: (error){
setState(() {});
});
}
_refreshHttp(){
_page = 1;
_httpGoodsList();
}
_loadMoreHttp(){
_page ++;
_httpGoodsList();
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。