直播带货源码,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 顶部滚动栏+页面的更多相关文章

  1. C# 带滚动栏的Label控件

    C# 带滚动栏的Label控件,用鼠标选的时候还是有点闪烁: namespace 带滚动栏的Label控件 { public class TextBoxLabel : System.Windows.F ...

  2. 直播带货APP源码开发为什么选择云服务器

    云服务器可以为直播带货APP源码提供弹性计算以及更高的运行效率,避免资源浪费,随着直播带货APP源码业务需求的变化,可以实时扩展或缩减计算资源.CVM支持按实际使用的资源计费,可以节约计算成本. 一. ...

  3. Bootstrap学习笔记上(带源码)

    阅读目录 排版 表单 网格系统 菜单.按钮 做好笔记方便日后查阅o(╯□╰)o bootstrap简介: ☑  简单灵活可用于架构流行的用户界面和交互接口的html.css.javascript工具集 ...

  4. 自己写一个jQuery垂直滚动栏插件(panel)

    html中原生的滚动栏比較难看,所以有些站点,会自己实现滚动栏,导航站点hao123在一个側栏中,就自己定义了垂直滚动栏,效果比較好看,截图例如以下: watermark/2/text/aHR0cDo ...

  5. [置顶] xamarin Tablayout+Viewpager+Fragment顶部导航栏

    最近几天不忙,所以把项目中的顶部导航栏的实现归集一下.android中使用TabLayout+ViewPager+Fragment制作顶部导航非常常见,代码实现也比较简单.当然我这个导航栏是基于xam ...

  6. 使用PagerSlidingTabStrip实现顶部导航栏

    使用PagerSlidingTabStrip配合ViewPager实现顶部导航栏. 效果图如下:          PagerSlidingTabStrip是github上的一个开源项目,项目地址如下 ...

  7. Android之仿今日头条顶部导航栏效果

    随着时间的推移现在的软件要求显示的内容越来越多,所以要在小的屏幕上能够更好的显示更多的内容,首先我们会想到底部菜单栏,但是有时候像今日头条新闻客户端要显示的内容太多,而且又想在主界面全部显示出来,所以 ...

  8. JS 带运动的返回顶部 小案例

    带运动的返回顶部:当滚动条在滚动的时候,滚动鼠标的滚轮,应该让滚动条停止滚动,清掉定时器.下面的方法b 就是清掉的方法 <!DOCTYPE html PUBLIC "-//W3C//D ...

  9. iOS开发项目实战——Swift实现ScrollView滚动栏功能

    手机作为一个小屏设备,须要显示的信息往往无法在一个屏幕上显示,此时就须要使用到滚动栏,当然除了像TableView这样能够自带滚动功能的. 假设一个界面上View较多,那就必须要使用到ScrollVi ...

  10. android 滚动栏下拉反弹的效果(相似微信朋友圈)

    微信朋友圈上面的图片封面,QQ空间说说上面的图片封面都有下拉反弹的效果,这些都是使用滚动栏实现的.下拉,当松开时候.反弹至原来的位置.下拉时候能看到背景图片.那么这里简介一下这样的效果的实现. 本文源 ...

随机推荐

  1. C++_虚函数

    1.目的: 派生类继承自基类.使用指针或引用访问派生类对象时,指针或引用本身所指向的类型可以是基类而不是派生类.如果派生类覆盖了基类中的方法,通过上述指针或引用调用该方法时,可以有两种结果: 调用到基 ...

  2. EPICS Archiver Appliance的定制部署2

    EPICS Archiver Appliance的定制部署1 按上面的步骤Archiver可以跑起来了,试了一下,发现waveform不能archive,看服务状态: 看起来正常,怀疑在profile ...

  3. ACR20新闻_RA指南更新_最大化应用MTX

    美国风湿病学院(ACR)学术年会2020新闻 译自Medscape官网 https://www.medscape.com/viewarticle/940636#vp_1 (注: 译文借助谷歌翻译助手, ...

  4. 生物标记钙卫蛋白在RA诊疗中的应用研究

    标签: 类风湿关节炎; 预测因子; 钙卫蛋白; S100A9 [文献摘记]生物标记钙卫蛋白在RA诊疗中的应用研究 电邮发布日期:2016年4月20日 不断提升精确度和应用范围的组学技术正在帮助包括类风 ...

  5. 达标式减量策略又一例证(STRASS研究)

    标签: 类风湿关节炎; T2T策略; TNF抑制剂; 药物减停; STRASS研究 达标式减量策略又一例证(STRASS研究): RA维持期个体化减停TNF拮抗剂是可能的 电邮发布日期: 2016年1 ...

  6. 【译】.NET 7 中的性能改进(七)

    原文 | Stephen Toub 翻译 | 郑子铭 Arm64 在.NET 7中,大量的努力用于使Arm64的代码生成与x64的代码生成一样好或更好.我已经讨论了一些与架构无关的PR,还有一些是专门 ...

  7. Postgresql临时表(TEMPORARY TABLE)

    一.简介 PostgreSQL中的临时表分两种,一种是会话级临时表,一种是事务级临时表.在会话级临时表中,数据可以存在于整个会话的生命周期中,在事务级临时表中的数据只能存在于事务的生命周期中.默认创建 ...

  8. RocketMQ - 消费者进度保存机制

    RocketMQ设计了远程位点管理和本地位点管理两种位点管理方式.集群消费时,位点由客户端提交给Broker保存,具体实现代码在RemoteBrokerOffsetStore.java文件中:广播消费 ...

  9. MySQL 查询常用操作(0) —— 查询语句的执行顺序

    MySQL中明确查询语句的执行顺序极其重要,了解执行顺序才不至于犯一些简单错误,例如having 后面是否可以使用 select 中重命名的列名等问题.另外SQL中实际使用最频繁的就是查询(Quein ...

  10. pat乙级1014 福尔摩斯的约会

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int ...