Flutter : ListView : Scroll parent ListView when child ListView reach bottom - ClampingScrollPhysics not working in sized container

后端 未结 3 1648
醉酒成梦
醉酒成梦 2021-01-03 11:54

I\'m using Flutter version 1.12.13+hotfix.

I\'m looking for a solution to be able to scroll inside a ListView and when reached the bottom, automatically give scroll

相关标签:
3条回答
  • 2021-01-03 12:16

    Usually when I come across an issue like this, I use SingleChildScrollView with a column as the child, and then whatever I want as the children of that column. Here's some demo code.

    SingleChildScrollView
    (
      child: Column
      (
        children:
        [
         /* Your content goes here. */
        ]
      )
    )
    

    Let me know if that fits your use case

    0 讨论(0)
  • 2021-01-03 12:25

    Thanks for Hamed Hamedi solution :) ! I made a better solution, I think, based on NotificationListener ! (I discovered this functionnality thanks to him).

    @override
      Widget build(BuildContext context) {
        return Container(
          padding: EdgeInsets.all(8),
          color: Colors.yellow,
          child: ListView.builder(
            controller: controller,
            itemBuilder: (c, i) =>
            i == 10
              ? Container(
              height: 150,
              color: Colors.red,
              child: NotificationListener<OverscrollNotification>(
                onNotification: (OverscrollNotification value) {
                  if (value.overscroll < 0 && controller.offset + value.overscroll <= 0) {
                    if (controller.offset != 0) controller.jumpTo(0);
                    return true;
                  }
                  if (controller.offset + value.overscroll >= controller.position.maxScrollExtent) {
                    if (controller.offset != controller.position.maxScrollExtent) controller.jumpTo(controller.position.maxScrollExtent);
                    return true;
                  }
                  controller.jumpTo(controller.offset + value.overscroll);
                  return true;
                },
                child: ListView.builder(
                  itemBuilder: (c, ii) => Text('-->' + ii.toString()),
                  itemCount: 20,
                ),
              ),
            )
              : Text(i.toString()),
            itemCount: 45,
          ),
        );
      }
    

    The solution wrapped into StatelessWidget :

    import 'package:flutter/material.dart';
    
    class ScrollParent extends StatelessWidget {
      final ScrollController controller;
      final Widget child;
    
      ScrollParent({this.controller, this.child});
    
      @override
      Widget build(BuildContext context) {
        return NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification value) {
            if (value.overscroll < 0 && controller.offset + value.overscroll <= 0) {
              if (controller.offset != 0) controller.jumpTo(0);
              return true;
            }
            if (controller.offset + value.overscroll >= controller.position.maxScrollExtent) {
              if (controller.offset != controller.position.maxScrollExtent) controller.jumpTo(controller.position.maxScrollExtent);
              return true;
            }
            controller.jumpTo(controller.offset + value.overscroll);
            return true;
          },
          child: child,
        );
      }
    }
    
    0 讨论(0)
  • 2021-01-03 12:32

    A tricky way could be using NotificationListener. Put a Overscroll Notification Listener over your child scroll widget then ignore the pointer in case of overscroll. To let the child widget to scroll again in opposite direction, you have to set ignoring false after a short time. A detailed code sample:

    class _MyHomePageState extends State<MyHomePage> {
    
      var _scrollParent = false;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Container(
            color: Colors.yellow,
            child: ListView.builder(
              itemBuilder: (c, i) => i == 10
                  ? Container(
                      height: 150,
                      color: Colors.red,
                      child: IgnorePointer(
                        ignoring: _scrollParent,
                        child: NotificationListener<OverscrollNotification>(
                          onNotification: (_) {
    
                            setState(() {
                              _scrollParent = true;
                            });
    
                            Timer(Duration(seconds: 1), () {
                              setState(() {
                                _scrollParent = false;
                              });
                            });
    
                            return false;
                          },
                          child: ListView.builder(
                            itemBuilder: (c, ii) => Text('-->' + ii.toString()),
                            itemCount: 100,
                          ),
                        ),
                      ),
                    )
                  : Text(i.toString()),
              itemCount: 100,
            ),
          ),
        );
      }
    }
    

    There would be some flaws like double scrolling requirement by user to activate parent scroll event (first one will ignore the pointer), or using timer to disable ignoring that leads to misbehavior in fast scrolling actions. But the implementation simplicity towards other solutions would be immense.

    0 讨论(0)
提交回复
热议问题