flutter自定义分页器

使用flutter自定义一个分页器

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

先看看效果图

在这里插入图片描述

思路
  1. 首先要准备一个盒子,装载分页数字。
  2. 其次要考虑数据总数量在一定范围内该如何进行分页比较合理,比如:展示的要有多少的页数,隐藏起来要有多少的页数,从而对盒子进行规划
  3. 并且当页数改变的时候,对盒子内的页码参数进行合适的变化
以上是我的简单思路,具体还是看看源码
  • 第一,因为分页器的内容需要时常改变,所以,要使用 StatefulWidget
    	class Pager extends StatefulWidget {
    	  const Pager({Key? key}) : super(key: key);
    	
    	  @override
    	  State<Pager> createState() => _PagerState();
    	}
    	
    	class _PagerState extends State<Pager> {
    	  @override
    	  Widget 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个页码item
    	      for(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("下一页");
    	  }
    		
    	  @override
    	  Widget build(BuildContext context) {
    	    return Container();
    	  }
    	}
    
    
  • 第三,将页码展示在页面,在这里行内布局我使用 Row,里面的每个页码我用的容器 Container套入Text组件,样式可以自己根据项目需要定义
    	@override
      Widget 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;  // 上一页的widget
  late Widget nextWidget; // 下一页的widget
  int 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);

  @override
  State<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);
  }

  @override
  Widget 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,
    );
  }
}

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

感谢观看!!!

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flutter中的自定义Controller是指可以控制和管理特定组件状态的类。通过自定义Controller,我们可以实现对组件的状态进行监听、更新和控制。 在Flutter中,常用的自定义Controller是StatefulWidget的Controller,也称为StateController。StateController通常包含一个State对象,用于管理组件的状态,并提供一些方法来更新状态和通知组件重新构建。 下面是一个简单的示例,展示了如何创建一个自定义的Controller来管理一个计数的状态: ```dart class CounterController { int _count = 0; int get count => _count; void increment() { _count++; } } ``` 在上面的示例中,CounterController包含一个私有变量_count来保存计数的值,并提供了一个公共方法increment来增加计数的值。通过get方法count,我们可以获取当前计数的值。 在使用自定义Controller时,通常需要将其与StatefulWidget配合使用。下面是一个使用CounterController的示例: ```dart class CounterWidget extends StatefulWidget { @override _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { final CounterController _controller = CounterController(); @override Widget build(BuildContext context) { return Column( children: [ Text('Count: ${_controller.count}'), RaisedButton( child: Text('Increment'), onPressed: () { setState(() { _controller.increment(); }); }, ), ], ); } } ``` 在上面的示例中,CounterWidget使用CounterController来管理计数的状态。在build方法中,我们可以通过_controller.count获取当前计数的值,并通过_controller.increment方法来增加计数的值。当点击按钮时,我们调用setState方法来通知Flutter框架重新构建组件。 通过自定义Controller,我们可以更好地管理和控制组件的状态,使代码更加模块化和可维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值