PageView常见属性

Flutter中的轮动图以及抖音上下滑页切换视频功能等等,这些都可以通过 PageView 轻松实现

属性 描述
scrollDirection Axis.horizonta水平方向 Axis.vertical锤子方向
children 配置子元素
allowImplicitScrolling 缓存当前页面的前后两页
onPageChanged page改变的时候触发
controller 控制器
physics 滑动效果
pageSnapping 是否滑动到下一页
reverse 是否反向滑动

PageView 的使用

import 'package:flutter/material.dart';

class CategoryPage extends StatefulWidget {
  const CategoryPage({super.key});

  @override
  State<CategoryPage> createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {
  @override
  Widget build(BuildContext context) {
    return PageView(
      scrollDirection: Axis.vertical, // 上下滑动, 默认是水平方向就是左右滑动
      children: [
        Center(
          child: Text('第一屏', style: Theme.of(context).textTheme.headlineLarge,),
        ),
        Center(
          child: Text('第二屏', style: Theme.of(context).textTheme.headlineLarge,),
        ),
        Center(
          child: Text('第三屏', style: Theme.of(context).textTheme.headlineLarge,),
        ),
      ],
    );
  }
}

page

PageView.builder

import 'package:flutter/material.dart';

class CategoryPage extends StatefulWidget {
  const CategoryPage({super.key});

  @override
  State<CategoryPage> createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {
  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      itemBuilder: (context, index) {
        return Container(
          alignment: Alignment.center,
          color: Colors.blue[100 * (index % 9)],
          child: Text('CategoryPage $index'),
        );
      },
    );
  }
}

page1

PageView上拉无限加载的实现思路

import 'package:flutter/material.dart';

class CategoryPage extends StatefulWidget {
  const CategoryPage({super.key});

  @override
  State<CategoryPage> createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {
  List<Widget> _list = [];

  @override
  void initState() {
    super.initState();
    for(var i = 0; i < 10; i++){
      _list.add(ListTile(
        title: Text('我是第$i个列表'),
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return PageView(
      scrollDirection: Axis.vertical,
      onPageChanged: (index){
        print('当前是第$index页');
        // 实现无限循环
        if(index == _list.length - 1){
          _list.addAll([
            ListTile(
              title: Text('我是第${_list.length}个列表'),
            ),
            ListTile(
              title: Text('我是第${_list.length + 1}个列表'),
            ),
          ]);
        }
      },
      children: _list,
    );
  }
}

PageView实现一个轮播图

import 'package:flutter/material.dart';

class CategoryPage extends StatefulWidget {
  const CategoryPage({super.key});

  @override
  State<CategoryPage> createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {


  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 200,
      child: PageView(
        pageSnapping:true,
        children: [
          Container(
            color: Colors.red,
            child: Image.network('https://www.itying.com/images/flutter/1.png', fit: BoxFit.cover)
          ),
          Container(
            color: Colors.blue,
            child: Image.network('https://www.itying.com/images/flutter/2.png', fit: BoxFit.cover)
          ),
          Container(
            color: Colors.yellow,
            child: Image.network('https://www.itying.com/images/flutter/3.png', fit: BoxFit.cover)
          ),
        ],
      ),
    );

  }
}

PageView 实现一个无限轮播的轮播图

1. 创建一个自定义的轮播图组件 Image.dart

import 'package:flutter/material.dart';


class ImagePage extends StatelessWidget {
  final double width;
  final double height;
  final String url;
  const ImagePage({super.key, this.width = double.infinity, this.height = 200, required this.url});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      height: height,
      child: Image.network(url, fit: BoxFit.cover), 
    );
  }
}

2. 创建一个自定义的轮播图组件 ImagePageView.dart

import 'package:flutter/material.dart';

import 'image.dart';

class ImagePageView extends StatefulWidget {
  const ImagePageView({super.key});

  @override
  State<ImagePageView> createState() => _ImagePageViewState();
}

class _ImagePageViewState extends State<ImagePageView> {
   List<Widget> list = [];

   @override
    void initState() {
      super.initState();
      list = const [
        ImagePage(
          width: double.infinity,
          height: 200,
          url: 'https://www.itying.com/images/flutter/1.png'
        ),
        ImagePage(
          width: double.infinity,
          height: 200,
          url: 'https://www.itying.com/images/flutter/2.png'
        ),
        ImagePage(
          width: double.infinity,
          height: 200,
          url: 'https://www.itying.com/images/flutter/3.png'
        ),
      ];
    }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 200,
      child: PageView.builder(
        itemCount: 1000,
        itemBuilder: (context, index){
          return list[index%list.length]; // 0 1 2 0 1 2 0 1 2 这里用取余的方式实现无限轮播
        }), 

    );

  }
}

Fluuter 定时器

const timeout = Duration(seconds: 3);
var t=Timer.periodic(timeout, (timer) {
  print('afterTimer='+DateTime.now().toString()););
// timer.cancel(); // 取消定时器
});
t.cancel();
void dispose() {
    super.dispose();
    t.cancel();
}

PageController animateToPage自动切换页面

1. 创建一个自定义的轮播图组件 Image.dart

import 'package:flutter/material.dart';


class ImagePage extends StatelessWidget {
  final double width;
  final double height;
  final String url;
  const ImagePage({super.key, this.width = double.infinity, this.height = 200, required this.url});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      height: height,
      child: Image.network(url, fit: BoxFit.cover), 
    );
  }
}

2. 创建一个自定义的轮播图组件 swiper.dart

import 'dart:async';

import 'package:flutter/material.dart';

import 'image.dart';

class SwiperPage extends StatefulWidget {
  // ignore: prefer_typing_uninitialized_variables
  final double width;
  // ignore: prefer_typing_uninitialized_variables
  final double height;
  final List<String> list;

  const SwiperPage(
      {super.key,
      this.width = double.infinity,
      this.height = 200,
      required this.list});

  @override
  State<SwiperPage> createState() => _SwiperPageState();
}

class _SwiperPageState extends State<SwiperPage> {
  int _currentIndex = 0;
  late PageController _pageController;

  List<Widget> pagelist = [];
  late Timer timer;

  @override
  void initState() {
    super.initState();

    for (var i = 0; i < widget.list.length; i++) {
      pagelist.add(ImagePage(
        width: widget.width,
        height: widget.height,
        url: widget.list[i],
      ));
    }

    _pageController = PageController(
      initialPage: _currentIndex,
    );

    var timer = Timer.periodic(const Duration(seconds: 5), (t) {
      _pageController.animateToPage((_currentIndex + 1) % pagelist.length,
          duration: const Duration(microseconds: 200), curve: Curves.linear);
    });
  }

  @override
  void dispose() {
    super.dispose();
    timer.cancel();
    _pageController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        SizedBox(
          width: widget.width,
          height: widget.height,
          child: PageView.builder(
              controller: _pageController,
              onPageChanged: (index) {
                setState(() {
                  _currentIndex = index % pagelist.length;
                });
              },
              itemCount: 1000,
              itemBuilder: (context, index) {
                return pagelist[index %
                    pagelist.length]; // 0 1 2 0 1 2 0 1 2 这里用取余的方式实现无限轮播
              }),
        ),
        Positioned(
          bottom: 0,
          left: 0,
          right: 0,
          child: Container(
            color: Colors.black.withOpacity(0.3),
            padding: const EdgeInsets.all(10),
            child: Row(
              // 三个点
              mainAxisAlignment: MainAxisAlignment.center,
              children: pagelist.asMap().keys.map((e) {
                return Container(
                  width: 10,
                  height: 10,
                  margin: const EdgeInsets.all(5),
                  decoration: BoxDecoration(
                    color: e == _currentIndex ? Colors.red : Colors.white,
                    borderRadius: BorderRadius.circular(10),
                  ),
                );
              }).toList(),
            ),
          ),
        ),
      ],
    );
  }
}

3. 创建一个自定义的轮播图组件 ImagePageView.dart


import 'dart:async';

import 'package:flutter/material.dart';
import 'swiper.dart';

class ImagePageView extends StatefulWidget {
  const CategoryPage({super.key});

  @override
  State<ImagePageView> createState() => _ImagePageViewState();
}

class _ImagePageViewState extends State<ImagePageView> {
  List<String> list = [];

  @override
  void initState() {
    super.initState();
    list = const [
      'https://www.itying.com/images/flutter/1.png',
      'https://www.itying.com/images/flutter/2.png',
      'https://www.itying.com/images/flutter/3.png',
    ];
  }

  @override
  Widget build(BuildContext context) {
    return SwiperPage(
      list: list,
    );
  }
}

page1

AutomaticKeepAliveClientMixin 缓存PageView页面

import 'package:flutter/material.dart';

class PageViewKeepAlive extends StatefulWidget {
  const PageViewKeepAlive({super.key});

  @override
  State<PageViewKeepAlive> createState() => _PageViewKeepAliveState();
}

class _PageViewKeepAliveState extends State<PageViewKeepAlive> {
  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      scrollDirection: Axis.vertical,
      itemCount: 10,
      itemBuilder: (context, index) {
        return MyContainer(num: index);
      },
    );
  }
}

class MyContainer extends StatefulWidget {
  final int num;
  const MyContainer({super.key, required this.num});

  @override
  State<MyContainer> createState() => _MyContainerState();
}


// 自定义组件
class _MyContainerState extends State<MyContainer> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    print(widget.num); // 默认数据是没有缓存的,每次滑动都会执行build方法
    return Center(
      child: Text('第${widget.num}屏', style: Theme.of(context).textTheme.headlineLarge,),
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

自定义KeepAliveWrapper 缓存页面

1. 创建一个自定义keepAliveWrapper组件 keepAliveWrapper.dart

import 'package:flutter/material.dart';

class KeepAliveWrapper extends StatefulWidget {
  const KeepAliveWrapper(
      {Key? key, @required this.child, this.keepAlive = true})
      : super(key: key);
  final Widget? child;
  final bool keepAlive;
  @override
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    return widget.child!;
  }

  @override
  bool get wantKeepAlive => widget.keepAlive;
  @override
  void didUpdateWidget(covariant KeepAliveWrapper oldWidget) {
    if (oldWidget.keepAlive != widget.keepAlive) {
// keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中
      updateKeepAlive();
    }
    super.didUpdateWidget(oldWidget);
  }
}

2. 创建一个自定义的轮播图组件 ImagePageView.dart

import 'package:flutter/material.dart';

import 'keepAliveWrapper.dart';

class PageViewKeepAlive extends StatefulWidget {
  const PageViewKeepAlive({super.key});

  @override
  State<PageViewKeepAlive> createState() => _PageViewKeepAliveState();
}

class _PageViewKeepAliveState extends State<PageViewKeepAlive> {
  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      scrollDirection: Axis.vertical,
      itemCount: 10,
      itemBuilder: (context, index) {
        return KeepAliveWrapper(
          child: MyContainer(num: index),
        );
        // )MyContainer(num: index);
      },
    );
  }
}

class MyContainer extends StatefulWidget {
  final int num;
  const MyContainer({super.key, required this.num});

  @override
  State<MyContainer> createState() => _MyContainerState();
}


// 自定义组件
class _MyContainerState extends State<MyContainer> {
  @override
  Widget build(BuildContext context) {
    print(widget.num); // 默认数据是没有缓存的,每次滑动都会执行build方法
    return Center(
      child: Text('第${widget.num}屏', style: Theme.of(context).textTheme.headlineLarge,),
    );
  }

}

results matching ""

    No results matching ""