flutter自定义分页器

article/2025/8/24 4:47:08

使用flutter自定义一个分页器

最近在写flutter项目,项目刚好需要一个分页器,对数据进行分页处理,一开始想要在网上找有没有已经写好的插件,搜寻一会后还是想着自己写一个。

先看看效果图

在这里插入图片描述

思路

  1. 首先要准备一个盒子,装载分页数字。
  2. 其次要考虑数据总数量在一定范围内该如何进行分页比较合理,比如:展示的要有多少的页数,隐藏起来要有多少的页数,从而对盒子进行规划
  3. 并且当页数改变的时候,对盒子内的页码参数进行合适的变化

以上是我的简单思路,具体还是看看源码

  • 第一,因为分页器的内容需要时常改变,所以,要使用 StatefulWidget
    	class Pager extends StatefulWidget {const Pager({Key? key}) : super(key: key);@overrideState<Pager> createState() => _PagerState();}class _PagerState extends State<Pager> {@overrideWidget build(BuildContext context) {return Container();}}
    
  • 第二,准备展示具体的页码参数,我的思路是根据页码生成对应的widget,所以存放页码的容器使用 list ,但是这个数组需要根据你需要在页面上展示多少的可见页码和隐藏页码来决定
    	class _PagerState extends State<Pager> {List _list = [];  // 存放页码的数组int _total = 10;  // 页码数量(总数据量/一页需要展示多少条数据)int _pageIndex = 1;  // 当前页码/*假如:在一行上展示七个页码item,那么要对total进行分配,并且需要根据当前的页码来决定list里面页码的规划*/void managePage(){_list = [];  // 将页码数组制空if(_total <= 1) {  // 当页码数量小于等于1时就不需要页码了,直接跳过,此时list为空数组return;}if(_total <= 7) {  // 7:是我自己规定一行内展示的页码item数量,需要展示多少可以自己定义,当小于等于7时,直接进行展示这7个页码itemfor(var i = 0; i < _total; i++) {_list.add(i+1);}} else if(_pageIndex <= 4) {  // 当页码大于7后,则需要根据当前页码对有些页码进行隐藏_list = [1,2,3,4,5, "...", _total];} else if(_pageIndex > _total - 3) { // 以此类推_list = [1,2, "...", _total - 3, _total - 2, _total - 1,  _total];} else {   _list = [1, "...", _pageIndex - 1, _pageIndex, _pageIndex + 1, "...", _total];}// 页码制定好后,根据自己需求,加上前一页按钮,后一页按钮_list.insert(0, "上一页");_list.add("下一页");}@overrideWidget build(BuildContext context) {return Container();}}
  • 第三,将页码展示在页面,在这里行内布局我使用 Row,里面的每个页码我用的容器 Container套入Text组件,样式可以自己根据项目需要定义
    	@overrideWidget build(BuildContext context) {return Container(width: double.infinity,child: Row(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.spaceAround,children: _list.mapIndexed((index, ele) {if(index == 0) {return GestureDetector(onTap: () {if(_pageIndex > 1) {setState(() {_pageIndex--;// 改变页码在这里发送事件通知});}},child: buildPagerItem(child: ele),);}if(index == _list.length - 1) {return GestureDetector(onTap: () {if(_pageIndex < _total) {setState(() {_pageIndex++;// 改变页码在这里发送事件通知});}},child: buildPagerItem(child: ele),);}return GestureDetector(onTap: () {if(ele != "...") {setState(() {if(_pageIndex != ele) {_pageIndex = ele;// 改变页码在这里发送事件通知}});}},child: buildPagerItem(child: Text("$ele",// 当前页码对应的组件的样式style: ele == _pageIndex ? TextStyle() : TextStyle())),);}).toList(),),);}// 在这里我对 build 里面的内容进行抽取Widget buildPagerItem({required Widget child}) {return Container(width: 100,height: 50,alignment: Alignment.center,decoration: BoxDecoration(),margin: EdgeInsets.symmetric(),child: child,);}

最后上全部源码

import 'package:flutter/material.dart';
import 'package:collection/collection.dart';import 'package:dianying/core/extension/index.dart';class Pager extends StatefulWidget {late TextStyle activeTextStyle;  // 当前页码的文本样式late Widget preWidget;  // 上一页的widgetlate Widget nextWidget; // 下一页的widgetint total;  // 总页码数量late double containerWidth;  // 容器的宽度late MainAxisAlignment mainAxisAlignment;  // 页码横主轴对齐方式late TextStyle normalTextStyle;  // 其他页码的文本样式late double pagerItemWidth;  // 页码item的宽度late double pagerItemHeight; // 页码item的高度late BoxDecoration pagerItemDecoration;  // 页码item的样式ValueChanged pageChange;   // 页码改变的回调late EdgeInsetsGeometry pagerItemMargin;  // 页码item的边距Pager({Key? key,TextStyle? activeTextStyle,Widget? preWidget,Widget? nextWidget,required this.total,double? containerWidth,MainAxisAlignment? mainAxisAlignment,TextStyle? normalTextStyle,double? pagerItemWidth,double? pagerItemHeight,BoxDecoration? pagerItemDecoration,required this.pageChange,EdgeInsetsGeometry? pagerItemMargin}) :  activeTextStyle = activeTextStyle ?? TextStyle(color: Colors.white,fontSize: 14.px),preWidget = preWidget ?? Icon(Icons.arrow_left, color: Colors.red, size: 22.px),nextWidget = nextWidget ?? Icon(Icons.arrow_right, color: Colors.red, size: 22.px),containerWidth = containerWidth ?? double.infinity,mainAxisAlignment = mainAxisAlignment ?? MainAxisAlignment.spaceAround,normalTextStyle = normalTextStyle ?? TextStyle(color: Colors.red, fontSize: 14.px),pagerItemWidth = pagerItemWidth ?? 36.px,pagerItemHeight = pagerItemHeight ?? 30.px,pagerItemDecoration = pagerItemDecoration ?? BoxDecoration(color: Colors.black, borderRadius: BorderRadius.circular(3.px)),pagerItemMargin = pagerItemMargin ?? const EdgeInsets.all(0),super(key: key);@overrideState<Pager> createState() => _PagerState();
}class _PagerState extends State<Pager> {int _pageIndex = 1;List _list = [];void manageList() {_list = [];if(widget.total <= 1) {return;}if(widget.total <= 7) {for(var i = 0; i < widget.total; i++) {_list.add(i+1);}} else if(_pageIndex <= 4) {_list = [1,2,3,4,5, "...", widget.total];} else if(_pageIndex > widget.total - 3) {_list = [1,2, "...", widget.total - 3, widget.total - 2, widget.total - 1,  widget.total];} else {_list = [1, "...", _pageIndex - 1, _pageIndex, _pageIndex + 1, "...", widget.total];}_list.insert(0, widget.preWidget);_list.add(widget.nextWidget);}@overrideWidget build(BuildContext context) {return buildContent();}Widget buildContent() {manageList();return Container(width: widget.containerWidth,child: Row(mainAxisSize: MainAxisSize.min,mainAxisAlignment: widget.mainAxisAlignment,children: _list.mapIndexed((index, ele) {if(index == 0) {return GestureDetector(onTap: () {if(_pageIndex > 1) {setState(() {_pageIndex--;widget.pageChange(_pageIndex);});}},child: buildPagerItem(child: ele),);}if(index == _list.length - 1) {return GestureDetector(onTap: () {if(_pageIndex < widget.total) {setState(() {_pageIndex++;widget.pageChange(_pageIndex);});}},child: buildPagerItem(child: ele),);}return GestureDetector(onTap: () {if(ele != "...") {setState(() {if(_pageIndex != ele) {_pageIndex = ele;widget.pageChange(_pageIndex);}});}},child: buildPagerItem(child: Text("$ele",style: ele == _pageIndex ? widget.activeTextStyle : widget.normalTextStyle,)),);}).toList(),),);}Widget buildPagerItem({required Widget child}) {return Container(width: widget.pagerItemWidth,height: widget.pagerItemHeight,alignment: Alignment.center,decoration: widget.pagerItemDecoration,margin: widget.pagerItemMargin,child: child,);}
}

如果感觉不错,点个赞再走吧!!!

感谢观看!!!


http://chatgpt.dhexx.cn/article/Eyy98nKj.shtml

相关文章

手写一个简单的分页器

封装分页器 1. 前言 分页器基本上是任何网站必须要有的一个组件&#xff0c;为什么需要分页器&#xff0c;当后台传入了大量的数据&#xff0c;那么在前端拿到数据&#xff0c;如果直接展示很有可能或造成卡顿&#xff0c;同时消耗过多的内存&#xff0c;给用户带来的浏览效果就…

分页器(分页器基本操作、点击按钮分页、美化分页器)

分页器基本操作 用户访问一个网页或者查看某些数据&#xff0c;如果数据量过大肯定需要按页查看&#xff0c;不可能一个页面显示N条数据内容这里就用到了分页器 首先往数据库里插入数据&#xff0c;这里咱们进行脚本批量插入 # #脚本批量插入数据book_list []for i in range(2…

分页器

1.分页器 作用&#xff1a;干啥的&#xff1f;数据量大的话&#xff0c;可以分页获取&#xff0c;查看。 2.一次性插入多条数据 def add1(request):# 这样for循环会造成对数据库的大量访问&#xff0c;不建议这样添加# models.Book.objects.create(name连城诀%s%i,price10i)ll[…

分页器组件

作为前端三剑客的分页器在许多场景都能 使用&#xff0c;在实际工作中也有插件来快速实现分页器功能 但我们要了解原理&#xff0c;所以我们自己手搓个简单的分页器 先处理好静态组件 <template><div class"pagination"><button>1</button>…

分页器的介绍

一 、分页器的简介 在页面显示分页数据&#xff0c;需要用到django分页器组件 from django.core.paginator import Paginator paginator对象&#xff1a;paginator Paginator(user_list,10)#per_page:每页显示条目数量 #count &#xff1a;数据总个数#num_pages:总页数#page_…

自定义分页器

前端必须要掌握的分页器&#xff0c;轮播图&#xff0c;与日历 手写&#xff0c;掌握原理 1:分页功能实现 为什么很多项目采用分页功能&#xff1a;比如电商平台有很多数据。一次加载出来会卡住 采用分页功能 Element Ul是有相应的分页组件&#xff0c;使用起来超级简单…

【JS案例】分页器——使用原生JavaScript实现

在使用vue编写完一个分页器组件后&#xff0c;我对分页器的底层逻辑产生了兴趣&#xff0c;想在此组件的基础上再深入了解一些分页器的底层逻辑&#xff0c;了解vue与原生js的区别。我在github上看了一些大神写的分页器&#xff0c;属实牛逼&#xff0c;之后自己也根据他们的编…

zigbee-无线点灯-协调器节点

开发环境&#xff1a;IAR 8.10 Z-stack 2.5 功能&#xff1a;协调器与终端节点组网&#xff0c;实现点对点通信。终端向协调器发送“D1”&#xff0c;协调器LED灯闪烁。 流程图&#xff1a; 具体代码&#xff1a; 定义所需要的变量 端点描述符 endPointDesc_t GenericApp_e…

十分钟入门Zigbee

大部分教程通常都是已Zigbee原理开始讲解和学习&#xff0c;各种概念让初学者难以理解。本教程从一个小白的角度出发&#xff0c;入门无需任何Zigbee底层原理知识&#xff0c;只需要基本的MCU研发经验就可以掌握&#xff0c;让您快速实现zigbee组网和节点之间通信。 本教程采用…

第一章:zigbee学习笔记之简介(上)

注&#xff1a;文章转载自https://blog.csdn.net/tainjau/article/details/81540013 写在前面&#xff1a; 最近开始搞智能家居的项目&#xff0c;之前只是了解过zigbee&#xff0c;但是并未深入学习过&#xff0c;所以工作之余&#xff0c;忙里偷闲下&#xff0c;学习一下zigb…

zigbee菜鸟笔记(一)zigbee的基础知识

一.什么是zigbee 有问题发送邮件至468078841qq.com ZigBee&#xff0c;也称紫蜂&#xff0c;是一种低速短距离传输的无线网上协议&#xff0c;底层是采用IEEE 802.15.4标准规范的媒体访问层与物理层。主要特色有低速、低耗电、低成本、支持大量网上节点、支持多种网上拓扑、低…

TI CC2538 做ZigBee协调器控制飞利浦 Hue 调色灯

【源码、文档、软件、硬件、技术交流、技术支持&#xff0c;入口见文末】 一、实验准备 1.1 硬件准备 1.1.1 CC2538 模块 本文中使用的 CC2538 模块是带 PA 芯片&#xff08;CC2592&#xff09;的。此外&#xff0c;最好是带焊接好的底板&#xff0c;便于后面与串口转USB…

使用zigbee的协议栈进行协调器路由器终端初始化

实验目的: 使用协议栈,外加自己写的数码管的代码模块 配置协调器路由器终端,各自对应数码管数字C,R,E。 本身不是很细致,只是把一些重要步骤截了一下,IAR工程什么的默认大家都会了。 zigbee协议栈的下载 下载完找以下文件夹 找到下面两个文件夹,然后复制出来放到自己的…

zigbee z-stack 协调器断电后,重新上电无法恢复

1、是否宏定义了NV_RESTORE1&#xff1b;NV_INIT1&#xff1b;&#xff08;协调器、路由器、终端都要定义&#xff09;定义位置如下 2、下载模式选Erase flash&#xff0c;选择位置&#xff1a;&#xff08;20201117修正:实际调试发现如果不许选择erase flash 协调器断电重连&a…

ZigBee中协调器断电重连问题?

问题描述&#xff1a;如果你想实现一个完好的网络&#xff0c;协调器断电重启后还是能加入原来的网络&#xff0c;加上NV_RESTORE编译选项就可以&#xff0c;如果发现加上它&#xff0c;还是实现不了要求&#xff0c;就请作如下操作&#xff1f; 方法&#xff1a;如果加了NV_R…

Zigbee协调器主动使终端节点退网

我使用ZDP_MgmtLeaveReq()这个函数来让已知短地址的终端退网&#xff0c;代码如下&#xff1a;我这样使用的结果是&#xff0c;可以将节点退网&#xff0c;节点上也需要做一些配置。我在函数里禁止节点重连&#xff0c;但是节点退网后会获取到新的短地址重新入网&#xff0c;这…

ZIGBEE 工程内区分终端与协调器

目前已知&#xff0c;工程中区分是终端还是协调器&#xff0c;与工程中Tolls文件夹中的.cfg文件有关&#xff1a; 从project->Edit Configuration进去可以删减左边栏Workspace下拉的项&#xff1a; 区别终端、路由器和协调器是通过Options.. -> C/C Compiler -> Extra…

Zigbee应用开发 协调器控制多个终端

协调器控制多个终端 功能要求: 协调器通过串口向终端发送控制命令 发送1 则终端1 的D8灯亮 发送 2 则 终端2 的灯亮 发送 0 则 俩个终端都灭 实现过程&#xff1a; 当网络状态发生改变时&#xff0c;通过串口打印一串消息用来分辨串口调试对应着那种类型的Zigbee 终端编程&…

zigbee现存网络下更换协调器

应用场景&#xff1a;现场协调器坏了&#xff0c;更换协调器&#xff0c;只改panid、加密信息、信道等是不行的 因为之前坏掉的协调器已经创建了一个网络&#xff0c;即使旧协调器坏了&#xff0c;网络还在&#xff0c;新协调器如果开机前没有之前的网络设备处于开启状态&…