flutter: 父pageview和子pageview的滑动贯通

一,代码:

1,main.dart

import 'package:flutter/material.dart';
//import 'page/Explore_demo.dart';
import 'page/Home.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
      debugShowCheckedModeBanner: true,
      home: Home(),
      theme: ThemeData(
          appBarTheme: AppBarTheme(
            backgroundColor: Colors.yellow, // 设置导航栏颜色为黄色
          )
      ),
    );
  }
}

2, Home.dart

import 'package:flutter/material.dart';
import 'History_demo.dart';
import 'History2_demo.dart';
import 'MyView2_demo.dart';

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

  @override
  State<StatefulWidget> createState() {
    return HomeState();
  }
}

class HomeState extends State<Home> with SingleTickerProviderStateMixin {

  int _currentPageIndex = 0;

  // 提前创建3个视图,当点击tabbar的时候,调用setState的index来去对应的页面
  final List<Widget> pageLists = [
    HistoryDemo(),
    History2Demo(),
    MyviewDemo()
  ];

  late PageController pageController;

  @override
  void initState() {
    super.initState();
    pageController = PageController(
      /// 初始索引值
      initialPage: 0,
    );
  }

  @override
  void dispose() {
    super.dispose();
    /// 销毁 PageView 控制器
    pageController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 根据_currentPageIndex展示视图
        body: PageView(
          /// 控制跳转翻页的控制器
          controller: pageController,
          /// 页面滑动
          /// 这里设置 PageView 页面也能滑动
          onPageChanged: (index) {
            setState(() {
              // 更新当前的索引值
              _currentPageIndex = index;
            });
          },
          /// Widget 组件数组 , 设置多个 Widget 组件
          /// 同一时间只显示一个页面组件
          children: pageLists,
        ),
        // 设置底部tabbar
        bottomNavigationBar: BottomNavigationBar(
            currentIndex: _currentPageIndex,
            //onTap: _onTapHandler,
            onTap: (index) {
              setState(() {
                //_pageController.jumpToPage(index);
                pageController.animateToPage(
                  index,
                  duration: Duration(milliseconds: 300),
                  curve: Curves.easeInOut,
                );
                _currentPageIndex = index;
              });
            },
            // 如果items的数量超过三个的话,就需要设置这个属性,否者显示不出来
            type: BottomNavigationBarType.fixed,
            fixedColor: Colors.black,

            items: [
              BottomNavigationBarItem(
                  icon: Icon(Icons.explore),
                  label: "explore"
              ),
              BottomNavigationBarItem(
                  icon: Icon(Icons.history),
                  label: "history"
              ),
              BottomNavigationBarItem(
                  icon: Icon(Icons.person),
                  label: "My"
              ),
            ]
        )
    );
  }
}

3,

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'Home.dart';

class HistoryDemo extends StatefulWidget {
  @override
  _HistoryDemoState createState() => _HistoryDemoState();
}

class _HistoryDemoState extends State<HistoryDemo> {
  int currentIndex = 0;
  final PageController _pageController = PageController();
  @override
  Widget build(BuildContext context) {
    //得到父state
    HomeState? _ancestor = context.findAncestorStateOfType<HomeState>();
    //得到父state中的pageController
    PageController? _parentController = _ancestor?.pageController;

    return Container(
        color: Colors.white,
        child: Column(children: [
          Container(
              margin: EdgeInsets.only(top: 10),
              height: 80,
              child: Row(
                children: [
                  SizedBox(width: 20),
                  tabText("推荐", 0),
                  SizedBox(width: 50),
                  tabText("武汉", 1),
                  SizedBox(width: 50),
                  tabText("导购", 2)
                ],
              )
          ),
          Expanded(
              child: NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification notification) {
          if (notification is OverscrollNotification) {
             if (currentIndex == 2) {
               var overscrollNotification = notification as OverscrollNotification;
                print("需要切换到上一层");
               _parentController?.position.moveTo(
                   _parentController.offset + overscrollNotification.overscroll);
             }
          }
          return true;
          },

           child:PageView(
                physics: AlwaysScrollableScrollPhysics(),
                onPageChanged: (int page) {    //滑动时改变当前页面
                  setState(() {
                    currentIndex = page;
                  });
                },
                controller: _pageController,     //指定控制器
                scrollDirection: Axis.horizontal, //垂直滑动  默认水平滑动
                children: const [
                  Center(
                    child: Text("1"),
                  ),
                  Center(
                    child: Text("2"),
                  ),
                  Center(
                    child: Text("3"),
                  ),
                ],
              )
          )),
        ]));
  }

  /// 导航栏文本样式定义
  RichText tabText(String text1, int index) {
    return RichText(
        text:TextSpan(
        text: text1,
        style: TextStyle(color: currentIndex == index ? Colors.black : Colors.grey,
            fontSize: currentIndex == index ? 40 : 30),
        recognizer: TapGestureRecognizer()
          ..onTap = () {
            //print('点击文字触发方法');
            setState(() {
              currentIndex = index; // 修改状态并触发 UI 更新
            });
            //把pageview滑动到指定页
            _pageController.animateToPage(
              index,
              duration: Duration(milliseconds: 300),
              curve: Curves.easeInOut,
            );
          }),
    );
  }
}

说明:下面的代码用来实现当子pageview滑动到最后时,继续滑动父pageview

          Expanded(
              child: NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification notification) {
          if (notification is OverscrollNotification) {
             if (currentIndex == 2) {
               var overscrollNotification = notification as OverscrollNotification;
                print("需要切换到上一层");
               _parentController?.position.moveTo(
                   _parentController.offset + overscrollNotification.overscroll);
             }
          }
          return true;
          },

           child:PageView(

二,测试效果:

 

 

posted @ 2025-04-19 10:15  刘宏缔的架构森林  阅读(41)  评论(0)    收藏  举报