Flutter开发Widgets 之 PageView使用示例

目录
  • 构造方法以及参数:
  • 基本用法
  • 无限滚动
  • 实现指示器
  • 切换动画
  • 总结:

构造方法以及参数:

PageView可用于Widget的整屏滑动切换,如当代常用的短视频APP中的上下滑动切换的功能,也可用于横向页面的切换,如APP第一次安装时的引导页面,也可用于开发轮播图功能.

  PageView({
    Key? key,
    this.scrollDirection = Axis.horizontal, // 设置滚动方向 垂直 / 水平
    this.reverse = false,	// 反向滚动
    PageController? controller,	// 滚动控制类
    this.physics,	// 滚动逻辑 , 不滚动 / 滚动 / 滚动到边缘是否反弹
    this.pageSnapping = true,	// 如果设置 false , 则无法进行页面手势捕捉
    this.onPageChanged, 	// 页面切换时回调该函数
    List<Widget> children = const <Widget>[],
    this.dragStartBehavior = DragStartBehavior.start,
    this.allowImplicitScrolling = false,
    this.restorationId,
    this.clipBehavior = Clip.hardEdge,
  }) : assert(allowImplicitScrolling != null),
       assert(clipBehavior != null),
       controller = controller ?? _defaultPageController,
       childrenDelegate = SliverChildListDelegate(children),
       super(key: key);

具体参数说明:

scrollDirection主要是滚动的方向即horizontal(水平)和vertical(垂直)两个,默认是horizontal的

reverse这个就是规定了children(子节点)的排序是否是倒序,默认false。这个参数在ListView也有,一般在做IM工具聊天内容用ListView展示时需要倒序展示的。

controller可以传入一个PageController的实例进去,可以更好的控制PageView的各种动作,可以设置:

  • 初始页面(initialPage)、
  • 是否保存PageView状态(keepPage)
  • 每一个PageView子节点的内容占改视图的比例(viewportFraction)
  • 直接调转到指定的PageView的子节点的方法(jumpToPage
  • 动画(平滑移动)到指定的PageView的子节点的方法(animateToPage)
  • 到下一个PageView的子节点的方法(nextPage)
  • 到上一个PageView的子节点的方法(previousPage)
    从以上可以看出基本是普通轮播图组件的API

physics就是设置滑动效果:

  • NeverScrollablePhysics表示设置的不可滚动
  • BouncingScrollPhysics表示滚动到底了会有弹回的效果,就是iOS的默认交互
  • ClampingScrollPhysics表示滚动到底了就给一个效果,就是Android的默认交互
  • FixedExtentScrollPhysics就是ios经典选择时间组件UIDatePicker那种交互。

pageSnapping就是设置是不是整页滚动,默认是true.

dragStartBehavior这个属性是设置认定开始拖动行为的方式,可以选择的是down和start两个,默认是start. down是第一个手指按下认定拖动开始,start是手指拖动才算开始。

allowImplicitScrolling这个属性一般提供给视障人士使用的,默认是fasle

基本用法

PageView控件可以实现一个“图片轮播”的效果,PageView不仅可以水平滑动也可以垂直滑动,简单用法如下:

PageView(
      children: [
        Container(color: Colors.red,),
        Container(color: Colors.black,),
        Container(color: Colors.yellow,),
      ],
    );

PageView滚动方向默认是水平,可以设置其为垂直方向:

PageView(
    scrollDirection: Axis.vertical,
    ...
)

PageView配合PageController可以实现非常酷炫的效果,控制每一个Page不占满,

Container(
      height:200 ,
      child: PageView(
        scrollDirection: Axis.horizontal,
        controller: PageController(viewportFraction: 0.9),
        children: [
          Container(color: Colors.red,),
          Container(color: Colors.black,),
          Container(color: Colors.yellow,),
        ],
      ),
    );

PageController中属性initialPage表示当前加载第几页,默认第一页。

onPageChanged属性是页面发生变化时的回调,用法如下:

无限滚动

PageView滚动到最后时希望滚动到第一个页面,这样看起来PageView是无限滚动的:

List<Widget> pageList = [PageView1(), PageView2(), PageView3()];
PageView.builder(
    itemCount: 10000,
    itemBuilder: (context, index) {
        return pageList[index % (pageList.length)];
    },
)

实现指示器

指示器显示总数和当前位置,通过onPageChanged确定当前页数并更新指示器。

 int _currentPageIndex = 0;
  List<Widget> pageList = [ Container(color: Colors.red,),
    Container(color: Colors.black,),
    Container(color: Colors.yellow,),];
 _buildPageView(){
    return Center(
      child: Container(
        height: 230,
        child: Stack(
          children: [
            PageView.builder(itemBuilder: (context,index){
              var val = pageList[index%(pageList.length)];
              print(val);
              return _buildPageViewItem('${val}');
            }),
            Positioned(
                bottom: 20,
                left: 0,
                right: 0,
                child: Container(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: List.generate(pageList.length, (i){
                      return Container(
                        margin: EdgeInsets.symmetric(horizontal: 5),
                        width: 10,
                        height: 10,
                        decoration: BoxDecoration(
                          shape: BoxShape.circle,
                          color: _currentPageIndex==i?Colors.blue:Colors.grey
                        ),
                      );
                    }).toList(),
                  ),
                )
            )
          ],
        ),
      ),
    );
  }
  _buildPageViewItem(String txt,{Color color=Colors.red}){
    return Container(
      color: color,
      alignment: Alignment.center,
      child: Text(txt,style: TextStyle(color: Colors.white,fontSize: 25),),
    );
  }

切换动画

如此常见的切换效果显然不能体验我们独特的个性,我们需要更炫酷的方式,看下面的效果:

在滑出的时候当前页面逐渐缩小并居中,通过给PageController添加监听获取当前滑动的进度:

_pageController.addListener(() {
      setState(() {
        _currPageValue = _pageController.page;
      });
    });

全部代码:

/**
 * @Author wywinstonwy
 * @Date 2022/10/05 9:50 上午
 * @Description:
 */
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/material.dart';
class WyPageView1 extends StatefulWidget {
  const WyPageView1({Key? key}) : super(key: key);
  @override
  _WyPageViewState createState() => _WyPageViewState();
}
class _WyPageViewState extends State<WyPageView1> {
  int _currentPageIndex = 0;
  var imgList = [
    'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2877516247,37083492&fm=26&gp=0.jpg',
    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582796218195&di=04ce93c4ac826e19067e71f916cec5d8&imgtype=0&src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F344fda8b47808261c946c81645bff489c008326f15140-koiNr3_fw658'
  ];
  late PageController _pageController;
  var _currPageValue=0;
  //缩放系数
  double _scaleFactor = .8;
  //view page height
  double _height = 230.0;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _pageController=PageController(viewportFraction: 0.9);
    _pageController.addListener(() {
      setState(() {
        _currPageValue = _pageController.page;
      });
    });
  }
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _pageController.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getAppBar('PageView'),
      body: Container(
          height: _height,
          child: PageView.builder(
            itemBuilder: (context, index) => _buildPageItem(index),
            itemCount: 10,
            controller: _pageController,
          )),
    );
  }
  _buildPageItem(int index) {
    Matrix4 matrix4 = Matrix4.identity();
    if (index == _currPageValue.floor()) {
      //当前的item
      double currScale = (1 - (_currPageValue - index) * (1 - _scaleFactor)).toDouble();
      var currTrans = _height * (1 - currScale) / 2;
      matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
        ..setTranslationRaw(0.0, currTrans, 0.0);
    } else if (index == _currPageValue.floor() + 1) {
      //右边的item
      var currScale =
          _scaleFactor + (_currPageValue - index + 1) * (1 - _scaleFactor);
      var currTrans = _height * (1 - currScale) / 2;
      matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
        ..setTranslationRaw(0.0, currTrans, 0.0);
    } else if (index == _currPageValue.floor() - 1) {
      //左边
      var currScale = (1 - (_currPageValue - index) * (1 - _scaleFactor)).toDouble();
      var currTrans = _height * (1 - currScale) / 2;
      matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
        ..setTranslationRaw(0.0, currTrans, 0.0);
    } else {
      //其他,不在屏幕显示的item
      matrix4 = Matrix4.diagonal3Values(1.0, _scaleFactor, 1.0)
        ..setTranslationRaw(0.0, _height * (1 - _scaleFactor) / 2, 0.0);
    }
    return Transform(
      transform: matrix4,
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 10),
        child: Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(12),
            image: DecorationImage(
                image: NetworkImage(imgList[index % 2]), fit: BoxFit.fill),
          ),
        ),
      ),
    );
  }
}

gitdemo地址:gitee.com/wywinstonwy…

总结:

相比熟悉Android和IOS开发的同学都会比较熟悉ViewPager,可以在界面上滑动多个界面View的切换。在Flutter中同样有这样的组建那就是PageView,相比于ViewPager它有着更加强大的功能,毕竟Flutter中Widget是一等公民,在实际开发中也是比较实用的组件,可以提升开发效率。

以上就是Flutter开发Widgets 之 PageView使用示例的详细内容,更多关于Flutter开发Widgets PageView的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter EventBus事件总线的应用详解

    目录 前言 EventBus的简介 EventBus的实际应用 总结 前言 flutter项目中,有许多可以实现跨组件通讯的方案,其中包括InheritedWidget,Notification,EventBus等.本文主要探讨的是EventBus事件总线实现跨组件通讯的方法. EventBus的简介 EventBus的核心是基于Streams.它允许侦听器订阅事件并允许发布者触发事件,使得不同组件的数据不需要一层层传递,可以直接通过EventBus实现跨组件通讯. EventBus最主要是通过

  • Flutter pageview切换指示器的实现代码

    PageView 是一个滑动视图列表,它也是继承至 CustomScrollView 的. 在 PageView 里有三个构造函数: PageView - 创建一个可滚动列表. PageView.builder - 创建一个滚动列表,指定数量. PageView.custom - 创建一个可滚动的列表,自定义子项. 效果 代码 // Copyright 2017, the Flutter project authors. Please see the AUTHORS file // for de

  • flutter PageView实现左右滑动切换视图

    本文实例为大家分享了flutter PageView左右滑动切换视图的具体代码,供大家参考,具体内容如下 import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_x/base/

  • Flutter构建自定义Widgets的全过程记录

    目录 一.组合widget实现 二.通过自定义CustomPainter实现widgets 三.饼状图piechart.dart代码展示 四.实际效果图,eg: 附:Flutter中父widget调用子widget的方法 总结 一.组合widget实现 1.android和flutter自定义控件对比 Android中,一般会继承View或已经存在的某个控件,然后覆盖draw方法来实现自定义View.在Flutter中,一个自定义widget通常是通过组合其它widget来实现的,而不是继承.下

  • Flutter 语法进阶抽象类和接口本质区别详解

    目录 1. 接口存在的意义? 2. 继承 VS 实现 3. Dart 中接口与实现的特殊性 4.Dart 中抽象类作为接口的小细节 1. 接口存在的意义? 在 Dart 中 接口 定义并没有对应的关键字.可能有些人觉得 Dart 中弱化了 接口 的概念,其实不然.我们一般对接口的理解是:接口是更高级别的抽象,接口中的方法都是 抽象方法 ,没有方法体.通过接口的定义,我们可以通过定义接口来声明功能,通过实现接口来确保某类拥有这些功能. 不过你有没有仔细想过,为什么接口会存在,引入接口的概念是为了解

  • Flutter开发Widgets 之 PageView使用示例

    目录 构造方法以及参数: 基本用法 无限滚动 实现指示器 切换动画 总结: 构造方法以及参数: PageView可用于Widget的整屏滑动切换,如当代常用的短视频APP中的上下滑动切换的功能,也可用于横向页面的切换,如APP第一次安装时的引导页面,也可用于开发轮播图功能. PageView({ Key? key, this.scrollDirection = Axis.horizontal, // 设置滚动方向 垂直 / 水平 this.reverse = false, // 反向滚动 Pag

  • 用Flutter开发自定义Plugin的方法示例

    当你在开发flutter应用的时候,有时会需要调用native的api,往往遇到flutter并没有相应的package, 这时候flutter plugin就开始发挥作用了,这篇文章将会讲解开发一个简单flutter plugin的步骤和方法,好了,让我们开始动手吧. 1.在Android Studio 中创建一个Flutter Plugin 项目,如下图 上图中你能看到项目描述中写到,如果需要暴露Andorid或iOS的API给开发者时,选择"Plugin"项目类型. 这个项目我们

  • Android开发组件flutter的20个常用技巧示例总结

    目录 1.map遍历快速实现边距,文字自适应改变大小 2.使用SafeArea 添加边距 3.布局思路 4.获取当前屏幕的大小 5.文本溢出显示省略号 6.一个圆角带搜索icon的搜索框案例 7.修改按钮的背景色 8.tab切换实例 9.点击事件组件点击空白区域不触发点击 10.使用主题色 11.往安卓模拟器中传图片 12.控制text的最大行数显示影藏文字 13.去掉默认的抽屉图标 14.图片占满屏 15.倒计时 16.固定底部 17.添加阴影 18.隐藏键盘 19.获取父级组件大小 20.点

  • Flutter开发技巧ListView去除水波纹方法示例

    正文 ScrollConfiguration( behavior: NoScrollBehaviorWidget(), child: ListView( ...... ...... ), ), 调用ScrollConfiguration官方类,实现behavior NoScrollBehaviorWidget用于去除水波纹的自定义Widget import 'package:flutter/material.dart'; /// 去除listview水印 /// ScrollConfigurat

  • 使用Flutter开发的抖音国际版实例代码详解

    简介 最近花了两天时间研究使用Flutter开发一个抖音国际版. 个人感觉使用Flutter开发app快得不要不要的额. 两天就基本可以开发个大概出来. 最主要是热重载,太方便实时调整UI布局了. 相应速度极快. 如下图: 主要项目架构 详细说明一下,开发主要在lib文件夹 pubspec.yaml是配置插件的位置,如http: ^0.12.0+4,类似依赖组件. common文件夹存放的是重写的网络组件,以及图标组件icons.dart config文件夹存放的api.dart,wei调用的a

  • 如何使用Flutter开发一款电影APP详解

    前言 使用Flutter开发一款App是一件非常愉快的事情,其出色的性能.跨多端以及数量众多的原生组件都是我们选择Flutter的理由!今天我们就来使用Flutter开发一款电影类的App,先看下App的截图. 从main.dart开始 在Flutter里main.dart是应用开始的地方: import 'package:flutter/material.dart'; import 'package:movie/utils/router.dart' as router; void main()

  • Flutter开发之路由与导航的实现

    如果说构成视图元素的基本单位是组件,那么构成应用程序的基本单位就是页面.对于拥有多个页面的应用程序而言,如何从一个页面平滑地过渡到另一个页面,是技术框架需要考虑的问题. 在前端开发中,可以使用路由框架来统一管理页面及它们之间的跳转.在Android中路由指的是一个Activity,在iOS中指的是一个ViewController,可以通过startActivity或pushViewController来打开一个新的路由.在Flutter中,路由的管理和导航借鉴了前端和客户端的设计思路,需要使用R

  • flutter 路由跳转的实现示例

    路由 做Android/iOS原生开发的时候,要打开一个新的页面,你得知道你的目标页面对象,然后初始化一个Intent或者ViewController,再通过startActivity或者pushViewController来推出一个新的页面,不能跟web一样,直接丢一个链接地址就跳转到新的页面.当然,可以自己去加一个中间层来实现这些功能. Flutter里面是原生支持路由的.Flutter的framework提供了路由跳转的实现.我们可以直接使用这些功能. Flutter路由介绍 Flutte

  • Flutter 容器盒子模型的使用示例

    在讲 Flutter 的盒子模型前,先看看HTML 中的盒子模型.如下图所示,一个页面元素包括了与父级容器的外边距(margin),自身内容与边框的内边距(padding).外边距 和内边距都可以通过 LTRB (左.上.右.下)单独设定四个方向的大小. Flutter 的盒子模型和 HTML 的是一样的,而通用的容器 Container 就相当于是一个通用的容器,和 HTML 的 div 标签一样.如果要控制一个元素的尺寸,外边距,内边距和边框,最通用的做法是使用 Container 容器将元

  • Flutter开发之动态权限的使用

    目录 基本使用 1,配置权限 动态权限申请 4.3.0 5.0.0 众所周知,Android在6.0版本后将权限修改成了动态权限,而iOS则一直使用的是动态权限,所以在Flutter应用开发中如果涉及到一些危险权限,就需要进行动态申请,动态申请权限可以使用Flutter的permission_handler. 基本使用 1,配置权限 首先,打开Android工程下的AndroidManifest.xml文件,具体路径如下:在android\app\src\main\AndroidManifest

随机推荐