flutter开发实战-实现首页分类目录入口切换功能

在开发中经常遇到首页的分类入口,如美团的美食团购、打车等入口,左右切换还可以分页更多展示。

一、使用flutter_swiper_null_safety

在pubspec.yaml引入

dart 复制代码
  # 轮播图
  flutter_swiper_null_safety: ^1.0.2

二、实现swiper分页代码

由于我这里按照一页8条展示,两行四列展示格式。

当列表list传入的控件时候,一共的页数为

dart 复制代码
int getSwiperPageNumber() {
    int allLength = widget.list.length;
    int aPageNum = getSwiperOnePageNumber();
    if (allLength % aPageNum == 0) {
      return (allLength / aPageNum).toInt();
    }

    return (allLength / aPageNum).toInt() + 1;
  }

通过列表,一页数量计算每一页应该展示多少个按钮。

dart 复制代码
List getSwiperPagerItems(int pagerIndex) {
    List pagerItems = [];
    int allLength = widget.list.length;
    int aPageNum = getSwiperOnePageNumber();
    int start = pagerIndex * aPageNum;
    int end = (pagerIndex + 1) * aPageNum;
    if (end > allLength) {
      end = allLength;
    }
    pagerItems = widget.list.sublist(start, end);

    return pagerItems;
  }

一共pages的列表

dart 复制代码
int pagerNumber = getSwiperPageNumber();
    for (int index = 0; index < pagerNumber; index++) {
      CategorySwiperPagerItem swiperPagerItem = CategorySwiperPagerItem();
      swiperPagerItem.pagerIndex = index;
      swiperPagerItem.pagerItems = getSwiperPagerItems(index);
      swiperPagers.add(swiperPagerItem);
    }

通过使用flutter_swiper_null_safety来显示

dart 复制代码
Swiper(
        // 横向
        scrollDirection: Axis.horizontal,
        // 布局构建
        itemBuilder: (BuildContext context, int index) {
          CategorySwiperPagerItem swiperPagerItem = swiperPagers[index];
          return HomeCategoryPager(
            pagerIndex: swiperPagerItem.pagerIndex,
            pageItems: swiperPagerItem.pagerItems,
            width: itemWidth,
            height: itemHeight,
            containerHeight: showHeight,
            containerWidth: width,
          );
        },
        //条目个数
        itemCount: swiperPagers.length,
        // 自动翻页
        autoplay: false,
        // pagination: _buildSwiperPagination(),
        // pagination: _buildNumSwiperPagination(),
        //点击事件
        // onTap: (index) {
        //   LoggerManager().debug(" 点击 " + index.toString());
        // },
        // 相邻子条目视窗比例
        viewportFraction: 1,
        // 用户进行操作时停止自动翻页
        autoplayDisableOnInteraction: true,
        // 无限轮播
        loop: false,
        //当前条目的缩放比例
        scale: 1,
      ),

实现比较简单,

完整代码如下

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart';
import 'package:flutter_app_dfaceintl/config/resource_manager.dart';
import 'package:flutter_app_dfaceintl/utils/color_util.dart';
import 'package:flutter_app_dfaceintl/widget/common/show_gesture_container.dart';
import 'package:one_context/one_context.dart';
import 'package:flutter_app_dfaceintl/config/logger_manager.dart';

class CategorySwiperPagerItem {
  int pagerIndex = 0;
  List pagerItems = [];
}

class HomeCategoryWidget extends StatefulWidget {
  const HomeCategoryWidget({
    Key? key,
    required this.rowNumber,
    required this.numberOfPerRow,
    required this.list,
    required this.screenWidth,
  }) : super(key: key);

  // 多少行
  final int rowNumber;

  // 一行几个
  final int numberOfPerRow;

  final List list;

  final double screenWidth;

  @override
  State<HomeCategoryWidget> createState() => _HomeCategoryWidgetState();
}

class _HomeCategoryWidgetState extends State<HomeCategoryWidget> {
  double showHeight = 0.0;
  double containVPadding = 5.0;
  double containHPadding = 10.0;

  List<CategorySwiperPagerItem> swiperPagers = [];

  bool showPagination = false;

  @override
  void initState() {
    // TODO: implement initState

    double containerHeight = getContainerMaxHeight(widget.screenWidth);
    showHeight = containerHeight + 2 * containVPadding;

    int pagerNumber = getSwiperPageNumber();
    for (int index = 0; index < pagerNumber; index++) {
      CategorySwiperPagerItem swiperPagerItem = CategorySwiperPagerItem();
      swiperPagerItem.pagerIndex = index;
      swiperPagerItem.pagerItems = getSwiperPagerItems(index);
      swiperPagers.add(swiperPagerItem);
    }

    if (swiperPagers.length > 1) {
      showPagination = true;
    }

    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double width = widget.screenWidth;
    double itemWidth = (width - 2 * containHPadding) / widget.numberOfPerRow;
    double itemHeight = itemWidth;
    return Container(
      width: width,
      height: showHeight,
      margin: EdgeInsets.symmetric(vertical: 5.0),
      padding: EdgeInsets.symmetric(
        vertical: containVPadding,
        horizontal: containHPadding,
      ),
      color: Colors.white,
      child: Swiper(
        // 横向
        scrollDirection: Axis.horizontal,
        // 布局构建
        itemBuilder: (BuildContext context, int index) {
          CategorySwiperPagerItem swiperPagerItem = swiperPagers[index];
          return HomeCategoryPager(
            pagerIndex: swiperPagerItem.pagerIndex,
            pageItems: swiperPagerItem.pagerItems,
            width: itemWidth,
            height: itemHeight,
            containerHeight: showHeight,
            containerWidth: width,
          );
        },
        //条目个数
        itemCount: swiperPagers.length,
        // 自动翻页
        autoplay: false,
        // pagination: _buildSwiperPagination(),
        // pagination: _buildNumSwiperPagination(),
        //点击事件
        // onTap: (index) {
        //   LoggerManager().debug(" 点击 " + index.toString());
        // },
        // 相邻子条目视窗比例
        viewportFraction: 1,
        // 用户进行操作时停止自动翻页
        autoplayDisableOnInteraction: true,
        // 无限轮播
        loop: false,
        //当前条目的缩放比例
        scale: 1,
      ),
    );
  }

  int getSwiperOnePageNumber() {
    return widget.numberOfPerRow * widget.rowNumber;
  }

  int getSwiperPageNumber() {
    int allLength = widget.list.length;
    int aPageNum = getSwiperOnePageNumber();
    if (allLength % aPageNum == 0) {
      return (allLength / aPageNum).toInt();
    }

    return (allLength / aPageNum).toInt() + 1;
  }

  List getSwiperPagerItems(int pagerIndex) {
    List pagerItems = [];
    int allLength = widget.list.length;
    int aPageNum = getSwiperOnePageNumber();
    int start = pagerIndex * aPageNum;
    int end = (pagerIndex + 1) * aPageNum;
    if (end > allLength) {
      end = allLength;
    }
    pagerItems = widget.list.sublist(start, end);

    return pagerItems;
  }

  double getContainerMaxHeight(double screenWidth) {
    double width = screenWidth;
    double itemSize = (width - 2 * containHPadding) / widget.numberOfPerRow;
    double maxHeight = itemSize * widget.rowNumber;

    int allLength = widget.list.length;
    if (allLength <= widget.numberOfPerRow) {
      maxHeight = itemSize;
    }

    return maxHeight;
  }
}

class HomeCategoryPager extends StatelessWidget {
  const HomeCategoryPager({
    Key? key,
    required this.pagerIndex,
    required this.pageItems,
    required this.width,
    required this.height,
    this.containerWidth,
    this.containerHeight,
  }) : super(key: key);

  final int pagerIndex;

  final List pageItems;

  final double width;
  final double height;

  final double? containerWidth;
  final double? containerHeight;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: containerWidth,
      height: containerHeight,
      child: Wrap(
        children: pageItems
            .map((e) => HomeCategoryItem(
                  width: width,
                  height: height,
                ))
            .toList(),
      ),
    );
  }
}

class HomeCategoryItem extends StatelessWidget {
  const HomeCategoryItem({
    Key? key,
    required this.width,
    required this.height,
  }) : super(key: key);

  final double width;
  final double height;

  @override
  Widget build(BuildContext context) {
    return ShowGestureContainer(
      padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
      width: width,
      height: height,
      highlightedColor: ColorUtil.hexColor(0xf0f0f0),
      onPressed: () {
        LoggerManager().debug("ShowGestureContainer");
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          buildIcon(),
          Padding(
            padding: EdgeInsets.only(top: 5.0),
            child: buildTitle(),
          ),
        ],
      ),
    );
  }

  Widget buildTitle() {
    return Text(
      "栏目",
      textAlign: TextAlign.left,
      maxLines: 2,
      overflow: TextOverflow.ellipsis,
      softWrap: true,
      style: TextStyle(
        fontSize: 12,
        fontWeight: FontWeight.w500,
        fontStyle: FontStyle.normal,
        color: ColorUtil.hexColor(0x444444),
        decoration: TextDecoration.none,
      ),
    );
  }

  Widget buildIcon() {
    return Icon(
      Icons.access_alarm,
      size: 32.0,
      color: Colors.brown,
    );
  }
}

三、小结

flutter开发实战-实现首页分类目录入口切换功能。Swiper实现如美团的美食团购、打车等入口,左右切换还可以分页更多展示。

学习记录,每天不停进步。

相关推荐
江上清风山间明月1 天前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能2 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人2 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen2 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang2 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang2 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1232 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-2 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力3 天前
Flutter应用开发:对象存储管理图片
flutter