直播带货源码,flutter 顶部滚动栏+页面

直播带货源码,flutter 顶部滚动栏+页面

 tabPage.dart

 

1
<br>import 'package:flutter/cupertino.dart';<br>import 'package:flutter/material.dart';<br>import 'package:flutter_trip/dao/travelDao.dart';<br>import 'package:flutter_trip/model/home/commonModel.dart';<br>import 'package:flutter_trip/model/travel/travelModel.dart';<br>import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';<br>import 'package:flutter_trip/widget/applicationWebView.dart';<br>import 'package:flutter_trip/widget/loadingContainer.dart';<br> <br>const _TRAVEL_URL =<br>    'https://m.ctrip.com/restapi/soa2/16189/json/searchTripShootListForHomePageV2?_fxpcqlniredt=09031014111431397988&__gw_appid=99999999&__gw_ver=1.0&__gw_from=10650013707&__gw_platform=H5';<br>const PAGE_SIZE = 10;<br> <br>class TabPage extends StatefulWidget {<br>  final String travelUrl;<br>  final String channelCode;<br> <br>  TabPage({Key? key, required this.travelUrl, required this.channelCode})<br>      : super(key: key);<br> <br>  @override<br>  State<StatefulWidget> createState() {<br>    // TODO: implement createState<br>    return _TabPageState();<br>  }<br>}<br> <br>class _TabPageState extends State<TabPage> with AutomaticKeepAliveClientMixin {<br>  List<TravelItem> travelItem = [];<br>  int pageIndex = 0;<br>  bool isLoad = true;<br> <br>  ScrollController _scrollController = ScrollController();<br> <br>  @override<br>  // TODO: implement wantKeepAlive<br>  bool get wantKeepAlive => true;<br> <br>  @override<br>  void initState() {<br>    // TODO: implement initState<br>    super.initState();<br>    _loadData();<br> <br>    _scrollController.addListener(() {<br>      if (_scrollController.position.pixels ==<br>          _scrollController.position.maxScrollExtent) {<br>        _loadData(loadMore: true);<br>        print("滚动到最底部有");<br>      }<br>    });<br>  }<br> <br>  @override<br>  Widget build(BuildContext context) {<br>    // TODO: implement build<br>    return Scaffold(<br>      body: LoadingContainer(<br>        isLoading: isLoad,<br>        cover: true,<br>        child: RefreshIndicator(<br>          onRefresh: _handleRefresh,<br>          child: MediaQuery.removePadding(<br>            removeTop: true,<br>            context: context,<br>            child: new StaggeredGridView.countBuilder(<br>              controller: _scrollController,<br>              crossAxisCount: 2,<br>              itemCount: travelItem.length,<br>              itemBuilder: (BuildContext context, int index) =><br>                  _TraveItem(index: index, item: travelItem[index]),<br>              staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),<br>              // mainAxisSpacing: 4.0,<br>              // crossAxisSpacing: 4.0,<br>            ),<br>          ),<br>        ),<br>      ),<br>    );<br>  }<br> <br>  Future<void> _handleRefresh() async {<br>    _loadData();<br>  }<br> <br>  _loadData({bool loadMore = false}) {<br>    if (loadMore) {<br>      pageIndex++;<br>    } else {<br>      pageIndex = 0;<br>    }<br> <br>    TravelDao.fetch(widget.travelUrl, widget.channelCode, pageIndex, PAGE_SIZE)<br>        .then((value) {<br>      setState(() {<br>        List<TravelItem> items = _filterItems(value.resultList);<br>        if (travelItem.length != 0) {<br>          travelItem.addAll(items);<br>        } else {<br>          travelItem = items;<br>        }<br>        isLoad = false;<br>      });<br>    }).catchError((onError) {<br>      print('网络请求出错 $onError');<br>    });<br>  }<br> <br>  List<TravelItem> _filterItems(List<TravelItem>? resultList) {<br>    List<TravelItem> items = [];<br>    if (resultList != null) {<br>      resultList.forEach((element) {<br>        if (element.article != null) {<br>          items.add(element);<br>        }<br>      });<br>    }<br>    return items;<br>  }<br>}<br> <br>class _TraveItem extends StatelessWidget {<br>  final int index;<br>  final TravelItem item;<br>  _TraveItem({Key? key, required this.index, required this.item})<br>      : super(key: key);<br> <br>  @override<br>  Widget build(BuildContext context) {<br>    // TODO: implement build<br>    return GestureDetector(<br>      onTap: () {<br>        if (item.article.urls.length > 0) {<br>          // Navigator.push(<br>          //     context,<br>          //     MaterialPageRoute(<br>          //         builder: (context) => ApplicationWebView(<br>          //               commonModel: CommonModel(<br>          //                   icon: '',<br>          //                   title: '详情',<br>          //                   url: item.article.urls[0].h5Url,<br>          //                   statusBarColor: 'ffffff',<br>          //                   hideAppBar: false),<br>          //             )));<br>        }<br>      },<br>      child: Card(<br>        child: PhysicalModel(<br>          color: Colors.transparent,<br>          clipBehavior: Clip.antiAlias,<br>          borderRadius: BorderRadius.circular(5),<br>          child: Column(<br>            crossAxisAlignment: CrossAxisAlignment.start,<br>            children: [<br>              _itemImage(),<br>              Container(<br>                padding: EdgeInsets.all(4),<br>                child: Text(<br>                  item.article.articleTitle,<br>                  textAlign: TextAlign.left,<br>                  maxLines: 2,<br>                  overflow: TextOverflow.ellipsis,<br>                  style: TextStyle(fontSize: 14, color: Colors.black),<br>                ),<br>              ),<br>              _infoText(),<br>            ],<br>          ),<br>        ),<br>      ),<br>    );<br>  }<br> <br>  _itemImage() {<br>    return Stack(<br>      children: [<br>        Image.network(item.article.images[0].dynamicUrl),<br>        Positioned(<br>          bottom: 8,<br>          left: 8,<br>          child: Container(<br>            padding: EdgeInsets.fromLTRB(5, 1, 5, 1),<br>            decoration: BoxDecoration(<br>              color: Colors.black54,<br>              borderRadius: BorderRadius.circular(10),<br>            ),<br>            child: Row(<br>              mainAxisAlignment: MainAxisAlignment.center,<br>              children: [<br>                Icon(<br>                  Icons.location_on_outlined,<br>                  size: 12,<br>                  color: Colors.white,<br>                ),<br>                LimitedBox(<br>                  maxWidth: 130,<br>                  child: Text(<br>                    _positonName(),<br>                    maxLines: 1,<br>                    overflow: TextOverflow.ellipsis,<br>                    style: TextStyle(fontSize: 12, color: Colors.white),<br>                  ),<br>                )<br>              ],<br>            ),<br>          ),<br>        )<br>      ],<br>    );<br>  }<br> <br>  String _positonName() {<br>    // return item.article.pois?.length == 0<br>    //     ? '未知'<br>    //     : item.article.pois![0]!.poiName;<br>    return item.article.pois?.length == 0<br>        ? '未知'<br>        : item.article.pois![0]?.poiName ?? '未知';<br>  }<br> <br>  _infoText() {<br>    return Container(<br>      padding: EdgeInsets.fromLTRB(6, 0, 6, 10),<br>      child: Row(<br>        mainAxisAlignment: MainAxisAlignment.spaceBetween,<br>        children: [<br>          Row(<br>            children: [<br>              PhysicalModel(<br>                color: Colors.transparent,<br>                clipBehavior: Clip.antiAlias,<br>                borderRadius: BorderRadius.circular(12),<br>                child: Image.network(<br>                  item.article.author!.coverImage!.dynamicUrl,<br>                  width: 24,<br>                  height: 24,<br>                ),<br>              ),<br>              Container(<br>                width: 90,<br>                padding: EdgeInsets.all(5),<br>                child: Text(<br>                  item.article.author!.nickName,<br>                  textAlign: TextAlign.left,<br>                  style: TextStyle(fontSize: 12),<br>                  maxLines: 1,<br>                  overflow: TextOverflow.ellipsis,<br>                ),<br>              )<br>            ],<br>          ),<br>          Row(<br>            mainAxisAlignment: MainAxisAlignment.end,<br>            children: [<br>              Icon(<br>                Icons.thumb_up,<br>                color: Colors.grey,<br>                size: 12,<br>              ),<br>              Container(<br>                padding: EdgeInsets.only(left: 3),<br>                child: Text(<br>                  item.article.likeCount.toString(),<br>                  maxLines: 1,<br>                  style: TextStyle(<br>                    color: Colors.grey,<br>                    fontSize: 10,<br>                  ),<br>                ),<br>              )<br>            ],<br>          )<br>        ],<br>      ),<br>    );<br>  }<br>}

 

 tabTravel.dart

 

1
<br>import 'package:flutter/material.dart';<br>import 'package:flutter_trip/dao/travelDao.dart';<br>import 'package:flutter_trip/dao/travelTabDao.dart';<br>import 'package:flutter_trip/model/travel/travelModel.dart';<br>import 'package:flutter_trip/model/travel/travelTabModel.dart';<br>import 'package:flutter_trip/pages/travel/tabPage.dart';<br> <br>class TabTravel extends StatefulWidget {<br>  @override<br>  _TabTravelState createState() => _TabTravelState();<br>}<br> <br>class _TabTravelState extends State<TabTravel><br>    with SingleTickerProviderStateMixin {<br>  late TabController tabController;<br>  late TravelTabModel travelTabModel;<br> <br>  bool isInit = false;<br>  List<TravelTab> tabs = [];<br> <br>  @override<br>  void initState() {<br>    //tabController = TabController(length: 0, vsync: this);<br>    // TODO: implement initState<br>    super.initState();<br>    TravelTabDao.fetch().then((TravelTabModel tabModel) {<br>      tabController = TabController(length: tabModel.tabs.length, vsync: this);<br> <br>      setState(() {<br>        tabs = tabModel.tabs;<br>        travelTabModel = tabModel;<br>      });<br>      this.isInit = true;<br>    }).catchError((error) {<br>      print("error $error");<br>    });<br>  }<br> <br>  @override<br>  Widget build(BuildContext context) {<br>    // TODO: implement build<br>    return Scaffold(<br>      body: Column(<br>        children: [<br>          isInit<br>              ? Container(<br>                  color: Colors.white,<br>                  padding:<br>                      EdgeInsets.only(top: MediaQuery.of(context).padding.top),<br>                  child: TabBar(<br>                    padding: EdgeInsets.zero,<br>                    controller: tabController,<br>                    isScrollable: true,<br>                    labelColor: Colors.black87,<br>                    labelPadding: EdgeInsets.only(left: 20, right: 20),<br>                    indicator: UnderlineTabIndicator(<br>                      borderSide: BorderSide(<br>                        color: Colors.lightBlue,<br>                        width: 3,<br>                      ),<br>                      insets: EdgeInsets.only(bottom: 10),<br>                    ),<br>                    tabs:<br>                        tabs.map((item) => Tab(text: item.labelName)).toList(),<br>                  ),<br>                )<br>              : Container(),<br>          Flexible(<br>            child: isInit<br>                ? TabBarView(<br>                    controller: tabController,<br>                    children: tabs<br>                        .map((item) => TabPage(<br>                            travelUrl: travelTabModel.url,<br>                            channelCode: item.groupChannelCode))<br>                        .toList(),<br>                    // children: tabs<br>                    //     .map((item) => Tab(text: item.groupChannelCode))<br>                    //     .toList(),<br>                  )<br>                : Container(),<br>          )<br>        ],<br>      ),<br>    );<br>  }<br> <br>  @override<br>  void dispose() {<br>    // TODO: implement dispose<br>    tabController.dispose();<br>    super.dispose();<br>  }

 

 以上就是 直播带货源码,flutter 顶部滚动栏+页面,更多内容欢迎关注之后的文章

 

posted @   云豹科技-苏凌霄  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-03-03 短视频系统源码,点开图片双指放大或双击放大
2022-03-03 直播软件开发,同一分类下仅状态栏切换有无特效两个版本
2022-03-03 直播软件搭建,横版自动滑动的轮播图
点击右上角即可分享
微信分享提示