Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ListView scrollable within PageView #50946

Open
altherat opened this issue Feb 17, 2020 · 33 comments
Open

Make ListView scrollable within PageView #50946

altherat opened this issue Feb 17, 2020 · 33 comments
Labels
c: proposal A detailed proposal for a change to Flutter f: gestures flutter/packages/flutter/gestures repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. P3 Issues that are less important to the Flutter project team-framework Owned by Framework team triaged-framework Triaged by Framework team

Comments

@altherat
Copy link
Contributor

altherat commented Feb 17, 2020

Unless I'm missing something, I don't believe it's possible to achieve scrolling on both a ListView (or SingleChildScrollView) and a PageView when the ListView is within the PageView and they both scroll in the same direction.

Consider the following simple example app with a vertical scrolling ListView within a vertical PageView:

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

class App extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: PageView(
          scrollDirection: Axis.vertical,
          children: <Widget>[
            ListView.builder(
              itemCount: 20,
              itemBuilder: (BuildContext context, int index) => ListTile(title: Text('Item $index'))
            ),
            Text('Page 2')
          ],
        )
      )
    );
  }

}

There is no way to get the PageView to scroll pages. I think expected behavior should be that when the ListView is scrolled to the bottom, the PageView should then handle the gesture. If I remember correctly, I believe it works like this with Android's RecyclerView and ViewPager.

I've played around with ScrollPhysics, ScrollBehavior, and NotificationListener such as listening for OverscrollNotification and then disabling scrolling for ListView, but I could not find a solution that worked well.

@TahaTesser TahaTesser reopened this Feb 18, 2020
@TahaTesser TahaTesser added d: stackoverflow Good question for Stack Overflow framework flutter/packages/flutter repository. See also f: labels. c: proposal A detailed proposal for a change to Flutter labels Feb 18, 2020
@VladyslavBondarenko VladyslavBondarenko added the f: scrolling Viewports, list views, slivers, etc. label Feb 18, 2020
@goderbauer
Copy link
Member

/cc @Piinks

@Piinks
Copy link
Contributor

Piinks commented Feb 20, 2020

Hi @altherat,

Flutter determines the priority that widgets receive gesture events like scrolling through a system called the gesture arena.
In your example, both the PageView and the ListView scroll vertically, and the ListView is claiming the gesture. You can see this decision process by adding this to your app:

import 'package:flutter/gestures.dart';

void main() {
  debugPrintGestureArenaDiagnostics = true;
  runApp(App());
}

There was some discussion of this in: #28139 (comment) as well as a reference to an article on gestures in Flutter that you may find helpful to achieve the behavior you are looking for.

@Piinks Piinks added the f: gestures flutter/packages/flutter/gestures repository. label Feb 20, 2020
@altherat
Copy link
Contributor Author

Hi @Piinks.

I've done a bit of looking at how gestures are handled and have come across those links, but because Scrollable handles the ListView's gestures, I don't believe it's possible for me to override them and handle them differently?

Even if I did have control, I'm not sure how I would implement the expected behavior because the ListView needs to only ignore scrolling down when has reached the bottom and then let the PageView handle it.

@SunPointed
Copy link

Hi @altherat Have you solved the problem yet? I have the same problem at https://github.com/SunPointed/MPFlutterChart/issues/102. I read this article https://medium.com/flutter-community/combining-multiple-gesturedetectors-in-flutter-26d899d008b2 but use this seem to need maintain all events(tap, longpress, scale etc.), it's too much trouble, is there an easier way for achieve this?

@altherat
Copy link
Contributor Author

Hey @SunPointed,

Yeah, I hacked up some sort of solution that seems to work but it's not perfect and I haven't tested it too much so it might have problems. I'm not sure if this will work the same with charts.

Basically with my solution I manage the vertical scrolling myself by wrapping the entire thing in RawGestureDetector and providing my own PageController to the PageView and a ScrollController to the ListView. I disable the default scrolling for the PageView and ListView by passing in NeverScrollableScrollPhysics for their physics. Then, when I handle the gestures on the RawGestureDetector, I just check if the ListView has reached the bottom and if it has, then the next vertical drag I let the PageController handle. Ideally I want that scrolling transfer to happen with a single gesture but I'm not sure that's possible this way.

Here's a sample app demonstrating it. My actual app only needs this ability when it scrolls to the bottom of the list (and not the top) so that's all that I accounted for.

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

class App extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Example()
      )
    );
  }

}

class Example extends StatefulWidget {

  @override
  _ExampleState createState() => _ExampleState();

}

class _ExampleState extends State<Example> {

  PageController _pageController;
  ScrollController _listScrollController;
  ScrollController _activeScrollController;
  Drag _drag;

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
    _listScrollController = ScrollController();
  }

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

  void _handleDragStart(DragStartDetails details) {
    if (_listScrollController.hasClients && _listScrollController.position.context.storageContext != null) {
      final RenderBox renderBox = _listScrollController.position.context.storageContext.findRenderObject();
      if (renderBox.paintBounds.shift(renderBox.localToGlobal(Offset.zero)).contains(details.globalPosition)) {
        _activeScrollController = _listScrollController;
        _drag = _activeScrollController.position.drag(details, _disposeDrag);
        return;
      }
    }
    _activeScrollController = _pageController;
    _drag = _pageController.position.drag(details, _disposeDrag);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    if (_activeScrollController == _listScrollController && details.primaryDelta < 0 && _activeScrollController.position.pixels == _activeScrollController.position.maxScrollExtent) {
      _activeScrollController = _pageController;
      _drag?.cancel();
      _drag = _pageController.position.drag(
        DragStartDetails(
          globalPosition: details.globalPosition,
          localPosition: details.localPosition
        ),
        _disposeDrag
      );
    }
    _drag?.update(details);
  }

  void _handleDragEnd(DragEndDetails details) {
    _drag?.end(details);
  }

  void _handleDragCancel() {
    _drag?.cancel();
  }

  void _disposeDrag() {
    _drag = null;
  }

  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: <Type, GestureRecognizerFactory>{
          VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
          () => VerticalDragGestureRecognizer(),
          (VerticalDragGestureRecognizer instance) {
            instance
              ..onStart = _handleDragStart
              ..onUpdate = _handleDragUpdate
              ..onEnd = _handleDragEnd
              ..onCancel = _handleDragCancel;
          }
          )
      },
      behavior: HitTestBehavior.opaque,
      child: PageView(
        controller: _pageController,
        scrollDirection: Axis.vertical,
        physics: const NeverScrollableScrollPhysics(),
        children: [
          ListView(
            controller: _listScrollController,
            physics: const NeverScrollableScrollPhysics(),
            children: List.generate(
              25,
              (int index) {
                return ListTile(
                  title: Text('Item $index')
                );
              }
            )
          ),
          Center(
            child: Text('Page 2')
          )
        ],
      )
    );
  }

}

@SunPointed
Copy link

@altherat thanks for your answer. I see in my problem I just a Chart provider, I don't know under what circumstances will users use these Charts(I don't know the parent of Chart in the users's view tree). Now I use a GestureArenaTeam to help Chart win in the arena, but this made the chart area not response the PageView.

@ra-develop
Copy link

ra-develop commented Jun 14, 2020

@altherat Thanks for idea. I used it in my exploration of scrolling with PageView https://github.com/ra-develop/PageView_test.Flutter.git
For best result of scrolling I changed _handleDragUpdate function. Short description of changes:

  1. Deleted check for details.primaryDelta < 0 - for scrolling to UP
  2. Added roundToDouble() for comparing _activeScrollController.position.pixels and _activeScrollController.position.maxScrollExtent - in this case scrolling worked stable. And you not need twice gesture for change element.
  3. Changed condition of comparing _activeScrollController.position.pixels and _activeScrollController.position.maxScrollExtent - for scrolling to UP
    See all changes below:
void _handleDragUpdate(DragUpdateDetails details) {
    if (_activeScrollController == _listScrollController 
    // && (details.primaryDelta < 0) 
    && (_activeScrollController.position.pixels.roundToDouble() >= _activeScrollController.position.maxScrollExtent.roundToDouble()
    || _activeScrollController.position.pixels <0 )) {
      _activeScrollController = _pageController;
      _drag?.cancel();
      _drag = _pageController.position.drag(
        DragStartDetails(
          globalPosition: details.globalPosition,
          localPosition: details.localPosition
        ),
        _disposeDrag
      );
    }
    _drag?.update(details);
  }

@rydmike
Copy link
Contributor

rydmike commented Jun 16, 2020

I run into this issue as well after a discussion in a Slack group. I think the original poster @altherat has the right idea and the ideal solution would imo also be if there would be some kind of way to tell PageView and ListView that you want to have similar behavior as in:

"There is no way to get the PageView to scroll pages. I think expected behavior should be that when the ListView is scrolled to the bottom, the PageView should then handle the gesture. If I remember correctly, I believe it works like this with Android's RecyclerView and ViewPager."

Or if that kind of behavior was just built into the Flutter framework for this kind of gesture/scrolling case. Might be difficult to do implicitly, but there should be some kind of way to tell the framework that you have this kind of case and you want the above mentioned behavior. The work-arounds to implement this kid of behavior that fights how the gesture detection is done by default, get very involved and tedious to implement, so it would be a nice addition if the framework could offer better support for it out of the box.

@ra-develop your experimentation looked very interesting and useful to others struggling with this issue. I noticed that the link to it is broken for some reason, I did find it though, so here it is again, hope this link works better: https://github.com/ra-develop/PageView_test.Flutter

And all of you following this issue/proposal, show it some love and give it thumbs up! I've heard Google uses up votes as one input in their prioritization. Not sure, can't hurt though! 😀

@Mayankk1995
Copy link

@altherat Thanks a lot for that example. Very helpful. Saved my day.

@xiaomanzijia
Copy link

xiaomanzijia commented Aug 13, 2020

@altherat @ra-develop Thanks for ideas. On top of your solution, I checked if the ListView has reached the top and optimized it, here is my solution: judge by the sliding direction, if it slides up to the bottom or down to the top, then next time drag it vertically and let PageController handle it.It worked fine.

void _handleDragUpdate(DragUpdateDetails details) {
    var scrollDirection = _activeScrollController.position.userScrollDirection;

    if (_activeScrollController == _listScrollController
        && ((scrollDirection == ScrollDirection.reverse) && _activeScrollController.offset.roundToDouble() >=
            _activeScrollController.position.maxScrollExtent
                .roundToDouble() ||
            (scrollDirection == ScrollDirection.forward) && _activeScrollController.offset < 0)) {
      _activeScrollController = pageController;
      _drag?.cancel();
      _drag = pageController.position.drag(
          DragStartDetails(
              globalPosition: details.globalPosition,
              localPosition: details.localPosition),
          _disposeDrag);
    }
    _drag?.update(details);
  }

@TahaTesser TahaTesser removed the d: stackoverflow Good question for Stack Overflow label Sep 25, 2020
@TahaTesser TahaTesser changed the title ListView within PageView Make ListView scrollable within PageView Sep 25, 2020
@khangpt
Copy link

khangpt commented Oct 4, 2020

Hey @SunPointed,

Yeah, I hacked up some sort of solution that seems to work but it's not perfect and I haven't tested it too much so it might have problems. I'm not sure if this will work the same with charts.

Basically with my solution I manage the vertical scrolling myself by wrapping the entire thing in RawGestureDetector and providing my own PageController to the PageView and a ScrollController to the ListView. I disable the default scrolling for the PageView and ListView by passing in NeverScrollableScrollPhysics for their physics. Then, when I handle the gestures on the RawGestureDetector, I just check if the ListView has reached the bottom and if it has, then the next vertical drag I let the PageController handle. Ideally I want that scrolling transfer to happen with a single gesture but I'm not sure that's possible this way.

Here's a sample app demonstrating it. My actual app only needs this ability when it scrolls to the bottom of the list (and not the top) so that's all that I accounted for.

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

class App extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Example()
      )
    );
  }

}

class Example extends StatefulWidget {

  @override
  _ExampleState createState() => _ExampleState();

}

class _ExampleState extends State<Example> {

  PageController _pageController;
  ScrollController _listScrollController;
  ScrollController _activeScrollController;
  Drag _drag;

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
    _listScrollController = ScrollController();
  }

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

  void _handleDragStart(DragStartDetails details) {
    if (_listScrollController.hasClients && _listScrollController.position.context.storageContext != null) {
      final RenderBox renderBox = _listScrollController.position.context.storageContext.findRenderObject();
      if (renderBox.paintBounds.shift(renderBox.localToGlobal(Offset.zero)).contains(details.globalPosition)) {
        _activeScrollController = _listScrollController;
        _drag = _activeScrollController.position.drag(details, _disposeDrag);
        return;
      }
    }
    _activeScrollController = _pageController;
    _drag = _pageController.position.drag(details, _disposeDrag);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    if (_activeScrollController == _listScrollController && details.primaryDelta < 0 && _activeScrollController.position.pixels == _activeScrollController.position.maxScrollExtent) {
      _activeScrollController = _pageController;
      _drag?.cancel();
      _drag = _pageController.position.drag(
        DragStartDetails(
          globalPosition: details.globalPosition,
          localPosition: details.localPosition
        ),
        _disposeDrag
      );
    }
    _drag?.update(details);
  }

  void _handleDragEnd(DragEndDetails details) {
    _drag?.end(details);
  }

  void _handleDragCancel() {
    _drag?.cancel();
  }

  void _disposeDrag() {
    _drag = null;
  }

  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: <Type, GestureRecognizerFactory>{
          VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
          () => VerticalDragGestureRecognizer(),
          (VerticalDragGestureRecognizer instance) {
            instance
              ..onStart = _handleDragStart
              ..onUpdate = _handleDragUpdate
              ..onEnd = _handleDragEnd
              ..onCancel = _handleDragCancel;
          }
          )
      },
      behavior: HitTestBehavior.opaque,
      child: PageView(
        controller: _pageController,
        scrollDirection: Axis.vertical,
        physics: const NeverScrollableScrollPhysics(),
        children: [
          ListView(
            controller: _listScrollController,
            physics: const NeverScrollableScrollPhysics(),
            children: List.generate(
              25,
              (int index) {
                return ListTile(
                  title: Text('Item $index')
                );
              }
            )
          ),
          Center(
            child: Text('Page 2')
          )
        ],
      )
    );
  }

}

Thanks for your idea.

@XuanTung95
Copy link

Hi Flutter team,
Is there a plan to make the scroll behavior available in the future or it is imposible?

@TN888
Copy link

TN888 commented May 13, 2021

I finally solved this problem, here's the solution posted on SO:
https://stackoverflow.com/questions/67515358/how-to-put-listview-inside-pageview-and-scroll-both-of-them-vertically/67515359#67515359

@Piinks
Copy link
Contributor

Piinks commented Jun 2, 2021

(Triage) I recently came across a few dupes of this issue. This one has the most upvotes, so I am going to close the rest and redirect them here. For reference they are:

I am wondering if the best way to implement this is through ScrollBehaviors. I don't know if we would want a unique ScrollPhysics that will defer on overscroll, or if we could instead introduce an OverscrollBehavior since ScrollPhysics has a lot more to it than just overscroll... not sure, but perhaps bringing everyone to one place from all of these issues will yield better collaboration and feedback. :)

@safvancentrric
Copy link

Container(
margin: EdgeInsets.all(10),
height: Get.height - 255,
child: ListView.builder(
itemCount: 5,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) =>
contentText(
padding: 10,
title:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'),
),
),

@safvancentrric
Copy link

Container(
margin: EdgeInsets.all(10),
height: Get.height - 255,
child: ListView.builder(
itemCount: 5,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) =>
contentText(
padding: 10,
title:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'),
),
),

when we place listview within container (may need height) ,listview properly scrollable within page view .(shrinkWrap: true, property of listview must be true)

@dnfield
Copy link
Contributor

dnfield commented Nov 2, 2021

Can you share meaningful user facing UI where you'd want this?

As a user I think I would find this confusing - what is the expected behavior when you have two axis aligned scrollables in the same plane?

@dnfield
Copy link
Contributor

dnfield commented Nov 2, 2021

I can think of one case - e.g. showing a text area that needs to scroll within the list.

@XuanTung95
Copy link

Can you share meaningful user facing UI where you'd want this?

It's the behavior of Android's RecyclerView and ViewPager.

@safvancentrric
Copy link

safvancentrric commented Nov 4, 2021 via email

@XuanTung95
Copy link

I can't catch your problem.

As the description of this ticket, the problem is: if the ListView is within the PageView with the same scroll direction, it got stuck on the page which contains ListView and cannot scroll to the other page of PageView. The code in the description still reproduces the problem, please check it.

If your problem is to make proper scrolling between nested scrollable widgets , you can provide physics as (physics:AlwaysScrollablePhysics()) of both scrollable view.

Do not seem to work, please provide code if it works for you.

@boris93
Copy link

boris93 commented Nov 17, 2021

This SO answer seems to solve the requirement using NotificationListener
https://stackoverflow.com/a/60712386/2476004

@ctrysbita
Copy link
Contributor

This SO answer seems to solve the requirement using NotificationListener https://stackoverflow.com/a/60712386/2476004

@boris93 This doesn't work when scrolling rapidly. The outside PageView always capture the gesture.

@polarby
Copy link

polarby commented Aug 8, 2022

@altherat Thanks for your awesome working example. Is there any possibility of applying a physics behavior for the nested drag motions?

@braj065
Copy link

braj065 commented Aug 25, 2022

What is the property of scrollController or DragUpdateDetails to observe to know when the scrollbar has reached the upper most part of the view. But the scroll is like when a bouncing scroll happens when we scroll a large list and it keeps scrolling smoothly.

@goderbauer goderbauer added the P6 label Oct 4, 2022
@hgraceb
Copy link
Contributor

hgraceb commented Oct 5, 2022

I have uploaded a package: nested_scroll_views, the example and result are as follows.

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

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scrollBehavior: const MaterialScrollBehavior().copyWith(
        dragDevices: PointerDeviceKind.values.toSet(),
      ),
      home: Scaffold(
        appBar: AppBar(title: const Text('nested_scroll_views')),
        body: NestedPageView(
          wantKeepAlive: true,
          scrollDirection: Axis.vertical,
          children: <Widget>[
            NestedListView.builder(
              wantKeepAlive: true,
              itemCount: 20,
              itemBuilder: (BuildContext context, int index) => ListTile(
                title: Text('Item $index'),
              ),
            ),
            const Text('Page 2'),
          ],
        ),
      ),
    );
  }
}

nested_scroll_views_example

@WMOH-DEV

This comment was marked as off-topic.

@flutter-triage-bot flutter-triage-bot bot added P3 Issues that are less important to the Flutter project and removed P6 labels Jun 28, 2023
@flutter-triage-bot flutter-triage-bot bot added team-framework Owned by Framework team triaged-framework Triaged by Framework team labels Jul 8, 2023
@UnreALi
Copy link

UnreALi commented Jul 20, 2023

hi @Hixie

I'm having similar issues with nested scrollable elements. The use of gesture detector and scroll is mandatory in mobile applications. This shouldn't be the natural behavior of scrollable elements in Flutter.

This issue reported in 2020 should still not be labeled p3 in 2023. My application feels broken for the end user, so it is not possible for me to publish it. I think it should be in higher priority triage. Is it possible to label it as P1?

issue.mp4

@ahmedijaz0007
Copy link

@ra-develop @altherat Thanks for the solution.

The only issue I was facing was when I tried to go up.
By just introducing "=" in this check, upward direction scrolls become a lot better. I was trying your approach in a page view that has multiple list views as its children. Your code can easily be adjusted to cater to all of them.

_activeScrollController.position.pixels <=0

@ra-develop
Copy link

@ahmedijaz0007 Well done! Have a nice coding!

@tirth-multipl
Copy link

tirth-multipl commented Nov 22, 2023

screen-20231122-185955.mp4

I want to implement ☝️ this UI, a Vertical-PageView consisting of Vertical ListViews. @dnfield here's an example!

@altherat @ra-develop @xiaomanzijia @rydmike thank you very much for your solutions!

@ra-develop
Copy link

screen-20231122-185955.mp4

I want to implement ☝️ this UI, a Vertical-PageView consisting of Vertical ListViews. @dnfield here's an example!

@altherat @ra-develop @xiaomanzijia @rydmike thank you very much for your solutions!
In my opinion what it is not difficult. Horizontal and Vertical Page Views has same principles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: proposal A detailed proposal for a change to Flutter f: gestures flutter/packages/flutter/gestures repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. P3 Issues that are less important to the Flutter project team-framework Owned by Framework team triaged-framework Triaged by Framework team
Projects
None yet
Development

No branches or pull requests