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

news2024/11/18 11:17:38

在这里插入图片描述

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

一、使用flutter_swiper_null_safety

在pubspec.yaml引入

  # 轮播图
  flutter_swiper_null_safety: ^1.0.2

二、实现swiper分页代码

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

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

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;
  }

一共pages的列表

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来显示

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,
      ),

实现比较简单,

完整代码如下

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;

  
  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;

  
  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();
  }

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

  
  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;

  
  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;

  
  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实现如美团的美食团购、打车等入口,左右切换还可以分页更多展示。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/837623.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C高级--day3(shell中的输入、命令置换符、数组、算数运算、分支结构)

#!/bin/bash pls ~/ -l | grep "^-" | wc -l qls ~/ -l | grep "^d" | wc -l echo "普通文件个数&#xff1a;$p" echo "目录文件个数&#xff1a;$q"#!/bin/bash read file posexpr index $file \. strexpr substr $file $((pos1)) 2…

Xposed回发android.os.NetworkOnMainThreadException修复

最近用xposed进行hook回发的时候&#xff0c;又出现了新的问题&#xff1b; android.os.NetworkOnMainThreadException&#xff1b; 在Android4.0以后&#xff0c;写在主线程&#xff08;就是Activity&#xff09;中的HTTP请求&#xff0c;运行时都会报错&#xff0c;这是因为…

解决K8S集群设置污点后,污点不生效,下发应用的问题

问题&#xff1a;在集群中部署了三个daemonset&#xff0c;一开始加了容忍Toleration&#xff0c;后边去掉Toleration后&#xff0c;还是一直往边缘节点上部署应用&#xff0c;非常离谱 解决&#xff1a;删掉Toleration后&#xff0c;需要把annotations一起删掉&#xff0c;因为…

Rust中的高吞吐量流处理

本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库&#xff0c;还使用这些库实现了一个流处理程序。 最后&#xff0c;作者介绍了如何通过测量空闲和阻塞时间来优化流处理程序的性能&#xff0c;并将这些内容同步至…

AcWing257. 关押罪犯(二分图+染色法)

输入样例&#xff1a; 4 6 1 4 2534 2 3 3512 1 2 28351 1 3 6618 2 4 1805 3 4 12884输出样例&#xff1a; 3512 解析&#xff1a; 二分&#xff0c;每次查看是否是二分图 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N2e45,M2e55…

【基础类】—DOM事件系统性学习

一、基本概念&#xff1a;DOM事件的级别 // DOM0 element.onclickfunction(){} // DOM2, 新增了冒泡和捕获 element.addEventListener(click,function(){}, false) // DOM3, 新增更多事件类型 鼠标、键盘等 element.addEventListener(keyup,function(){}, false)二、DOM事件模…

如何使用ONLYOFFICE+ffmpeg来给视频文件打马赛克

如何使用ONLYOFFICEffmpeg来给视频文件打马赛克 我这里之前写过很多关于ONLYOFFICE使用、安装的系列图文&#xff0c;也写过很多关于ffmpeg使用的图文&#xff0c;那么这次继续&#xff0c;把这两个开源软件放在一起&#xff0c;能碰撞出什么火花般的功能来。 这就是给视频文…

【Linux后端服务器开发】poll/epoll多路转接IO服务器

目录 一、poll原理 二、poll实现多路转接IO服务器 三、epoll函数接口 四、epoll的工作原理 五、epoll实现多路转接IO服务器 一、poll原理 poll函数接口 #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);// pollfd结构 struct pollfd …

c高级:day3

作业: 1. 整理思维导图 2.判断家目录下,普通文件的个数和目录文件的个数 #!/bin/bash ######################################################################## # File Name: zy1.sh # Created Time: 2023年08月04日 星期五 19时13分08秒 ##############################…

知识体系总结(八)SSM框架体系

文章目录 Spring基础1-1、Spring、SpringMVC、Mybatis与SpringBoot的区别1-2、Spring中常用的注解及作用1-3、Spring 框架中用到了哪些设计模式&#xff1f; Spring IoC 、 DI、Bean2-1、Spring IoC是什么&#xff0c;有什么好处&#xff0c;Spring中是怎么实现的&#xff1f;2…

《Kali渗透基础》13. 无线渗透(三)

kali渗透 1&#xff1a;无线通信过程1.1&#xff1a;Open 认证1.2&#xff1a;PSK 认证1.3&#xff1a;关联请求 2&#xff1a;加密2.1&#xff1a;Open 无加密网络2.2&#xff1a;WEP 加密系统2.3&#xff1a;WPA 安全系统2.3.1&#xff1a;WPA12.3.2&#xff1a;WPA2 3&#…

修复 Adob​​e After Effects 预览无法工作/播放的方法技巧

Adobe After Effects 允许您预览视频和音频&#xff0c;而无需将其渲染为最终输出。当您无法在此应用程序中预览视频和音频时&#xff0c;一定会感到沮丧。不过不用担心&#xff0c;您可以尝试以下方法来修复 After Effects 预览不起作用的问题。 技巧1&#xff1a;重启After …

SHEIN还说TEMU,2023跨境电商怎么选?

2023年要说跨境热门的平台有哪些&#xff0c;SHEIN与TEMU应该是名列前茅的。这两家一直以来给人感觉也都是比较相似的&#xff0c;他们的跨境斗法从未停歇。其实两者有相似之处&#xff0c;也有不同之处!作为跨境玩家&#xff0c;我们应该如何选择适合自己的平台呢?往下看。 一…

Qt 6. 其他类调用Ui中的控件

1. 把主类指针this传给其他类&#xff0c;tcpClientSocket new TcpClient(this); //ex2.cpp #include "ex2.h" #include "ui_ex2.h"Ex2::Ex2(QWidget *parent): QDialog(parent), ui(new Ui::Ex2) {ui->setupUi(this);tcpClientSocket new TcpClient…

一百四十一、Kettle——kettle8.2在Windows本地开启carte服务以及配置子服务器

一、目的 在kettle建好共享资源库后&#xff0c;为了给在服务器上部署kettle的carte服务躺雷&#xff0c;先在Windows本地测试一下怎么玩carte服务 二、Kettle版本以及在Windows本地安装路径 kettle版本是8.2 pdi-ce-8.2.0.0-342 kettle本地安装路径是D:\j…

【动态规划刷题 4】礼物的最大价值下降路径最小和

礼物的最大价值 在一个 m*n 的棋盘的每一格都放有一个礼物&#xff0c;每个礼物都有一定的价值&#xff08;价值大于 0&#xff09;。你可以从棋盘的左上角开始拿格子里的礼物&#xff0c;并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值…

Flutter iOS 集成使用 fluter boost

在 Flutter项目中集成完 flutter boost&#xff0c;并且已经使用了 flutter boost进行了路由管理&#xff0c;这时如果需要和iOS混合开发&#xff0c;这时就要到 原生端进行集成。 注意&#xff1a;之前建的项目必须是 Flutter module项目&#xff0c;并且原生项目和flutter m…

Kotlin~Visitor访问者模式

概念 将数据结构和操作分离&#xff0c;使操作集合可以独立于数据结构变化。 角色介绍 Visitor&#xff1a;抽象访问者&#xff0c;为对象结构每个具体元素类声明一个访问操作。Element&#xff1a;抽象元素&#xff0c;定义一个accept方法ConcreteElement&#xff1a;具体元…

HTML编码

目录 1.HTML编码概述2.实体编码3.URLcode编码4.unicode编码5.解码实例 1.HTML编码概述 通常一个网页中可解析的总共有三种编码&#xff0c;每种编码都能用来代替表示字符&#xff0c;按解析顺序依次是“html实体编码”“urlcode码”“Unicode码”&#xff0c;在执行过程中会在…

Flowable-顺序流

目录 顺序流标准顺序流定义图形标记XML内容使用示例 条件顺序流定义图形标记XML内容界面操作 默认顺序流定义图形标记XML内容使用示例视频教程 顺序流 顺序流是一端带有箭头的实线&#xff0c;可在流程图中连接流程内的各个元素&#xff0c;并显示各个元素的执行顺序。 Flowa…