如何“合并”在PageView内的TabBarView上滚动? [英] How to "merge" scrolls on a TabBarView inside a PageView?

查看:84
本文介绍了如何“合并”在PageView内的TabBarView上滚动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在其主页上使用PageView的应用程序。今天,我被分配在这些页面之一中插入TabBarView。问题是,当我在最后一个标签页中的两个标签页之间滚动时,向左滚动不会滚动PageView。



我需要一种方法来页面视图的滚动在选项卡视图的开始或结束时滚动。



我发现了一个与问题相反的问题:

  @override 
小部件build(BuildContext context){
//本地dragStartDetail。
DragStartDetails dragStartDetails;
//当前拖动实例-应该在过度滚动时实例化并与之同时更新。
拖动拖动;
return Column(
children:< Widget> [
TabBar(
labelColor:Colors.green,
indicatorColor:Colors.green,
控制器: _tabController,
标签:< Tab> [
const Tab(text: Dark),
const Tab(text: Normal),
const Tab(text: Light),
],
),
Expanded(
child:NotificationListener(
onNotification:(notification){
if(notification是ScrollStartNotification ){
dragStartDetails = notification.dragDetails;
}
if(notification is OverscrollNotification){
drag = _pageController.position.drag(dragStartDetails,(){});
drag.update(notification.dragDetails);
}
如果(通知是ScrollEndNotification){
drag?.c ancel();
}
返回true;
},
子项:TabBarView(
控制器:_tabController,
子项:< Widget> [
Container(color:Colors.green [800]),
容器(颜色:Colors.green),
容器(颜色:Colors.green [200]),
],
),
),
),
],
);
}




旧答案


以上可能无法处理某些极端情况。如果需要更多控制,下面的代码可提供相同的结果,但可以处理 UserScrollNotification 。我粘贴此内容是因为,它可能对其他想知道使用滚动<< c>滚动视图的轴的方向的人有用。

 如果(通知是ScrollStartNotification){
dragStartDetails = notification.dragDetails;
}

if(通知为UserScrollNotification&
notification.direction == ScrollDirection.forward&
!_tabController.indexIsChanging&
dragStartDetails!= null&&
_tabController.index == 0){
_pageController.position.drag(dragStartDetails,(){});
}

// Simialrly处理最后一个标签。
if(通知是UserScrollNotification&
notification.direction == ScrollDirection.reverse&&
!_tabController.indexIsChanging&&
dragStartDetails!= null& ;&
_tabController.index == _tabController.length-1){
_pageController.position.drag(dragStartDetails,(){});
}


I have an app that uses a PageView on its main page. Today, I got assigned to insert a TabBarView in one of these pages. The problem is that when I scroll the between the tabs when in the last tab, scrolling to the left won't scroll the PageView.

I need a way to make the scroll of page view scroll when at the start or end of the tabbarview.

I found a question with the inverted problem: flutter PageView inside TabBarView: scrolling to next tab at the end of page

However, the method stated there is not suitable to my issue.

I made a minimal example:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'TabBarView inside PageView',
        home: MyHomePage(),
      );
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final PageController _pageController = PageController();

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: Text('TabBarView inside PageView'),
        ),
        body: PageView(
          controller: _pageController,
          children: <Widget>[
            Container(color: Colors.red),
            GreenShades(),
            Container(color: Colors.yellow),
          ],
        ),
      );
}

class GreenShades extends StatefulWidget {
  @override
  _GreenShadesState createState() => _GreenShadesState();
}

class _GreenShadesState extends State<GreenShades>
    with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    this._tabController = TabController(length: 3, vsync: this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) => Column(
        children: <Widget>[
          TabBar(
            labelColor: Colors.green,
            indicatorColor: Colors.green,
            controller: _tabController,
            tabs: <Tab>[
              const Tab(text: "Dark"),
              const Tab(text: "Normal"),
              const Tab(text: "Light"),
            ],
          ),
          Expanded(
            child: TabBarView(
              controller: _tabController,
              children: <Widget>[
                Container(color: Colors.green[800]),
                Container(color: Colors.green),
                Container(color: Colors.green[200]),
              ],
            ),
          )
        ],
      );

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }
}

Note that, in this MRE, it's possible to reach the 3rd page if you drag the TabBar, but not if you drag the TabBarView.

How may I achieve this behavior?


Edit:

As stated by @Fethi, there's a similar question: Is it possible to swipe from an TabBarView content area to an adjacent PageView page?

However, the question was not answered satisfactorily, as the solution given does not really "blend" the scroll, although the behavior is similar to what was described. It doesn't scroll naturally.

解决方案

This is possible by using the PageController.postion attribute's drag method, which internally drags the ScrollPosition of the screen. This way, user can intuitively drag the pages like drag halfway and then leave or continue fully.

The idea is inspired from the other post to use the OverScrollNotification but add rather more step to continue intuitive dragging.

  1. Collect the DragstartDetail when user starts scrolling.
  2. Listen for OverScrollNotification and start the draging and at the same time update the drag using the drag.update with the DragUpdateDetails from OverscrollNotification method.
  3. On ScrollEndNotification cancel the the drag.

To keep the idea simple I am pasting only build method of the Tabs page.

A fully working example is available in this dart pad.

  @override
  Widget build(BuildContext context) {
    // Local dragStartDetail.
    DragStartDetails dragStartDetails;
    // Current drag instance - should be instantiated on overscroll and updated alongside.
    Drag drag;
    return Column(
      children: <Widget>[
        TabBar(
          labelColor: Colors.green,
          indicatorColor: Colors.green,
          controller: _tabController,
          tabs: <Tab>[
            const Tab(text: "Dark"),
            const Tab(text: "Normal"),
            const Tab(text: "Light"),
          ],
        ),
        Expanded(
          child: NotificationListener(
            onNotification: (notification) {
              if (notification is ScrollStartNotification) {
                dragStartDetails = notification.dragDetails;
              }
              if (notification is OverscrollNotification) {
                drag = _pageController.position.drag(dragStartDetails, () {});
                drag.update(notification.dragDetails);
              }
              if (notification is ScrollEndNotification) {
                drag?.cancel();
              }
              return true;
            },
            child: TabBarView(
              controller: _tabController,
              children: <Widget>[
                Container(color: Colors.green[800]),
                Container(color: Colors.green),
                Container(color: Colors.green[200]),
              ],
            ),
          ),
        ),
      ],
    );
  }

Old Answer

The above might not handle some edge cases. If you need more control below code provides the same result but you can handle UserScrollNotification. I am pasting this because, it might be useful for others who would like to know which direction the use is scrolling w.r.t the Axis of the ScrollView.

              if (notification is ScrollStartNotification) {
                dragStartDetails = notification.dragDetails;
              }

              if (notification is UserScrollNotification &&
                  notification.direction == ScrollDirection.forward &&
                  !_tabController.indexIsChanging &&
                  dragStartDetails != null &&
                  _tabController.index == 0) {
                _pageController.position.drag(dragStartDetails, () {});
              }

              // Simialrly Handle the last tab.
              if (notification is UserScrollNotification &&
                  notification.direction == ScrollDirection.reverse &&
                  !_tabController.indexIsChanging &&
                  dragStartDetails != null &&
                  _tabController.index == _tabController.length - 1) {
                _pageController.position.drag(dragStartDetails, () {});
              }

这篇关于如何“合并”在PageView内的TabBarView上滚动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆