1

I want to try Nested Scrolling ListView inside PageView future and download source code in Gitbub. But when I tried it, throw exception.

Error place on final

RenderBox renderBox = _listScrollController!
   .position.context.storageContext.findRenderObject!(); 

in _handleDragStart.

Below is my code.

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

class NestedContainerWidget extends StatefulWidget {
  @override
  _NestedContainerWidgetState createState() => _NestedContainerWidgetState();
}

class _NestedContainerWidgetState extends State<NestedContainerWidget> {
  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);
  }

  /*
   * If the listView is on Page 1, then change the condition as "details.primaryDelta < 0" and
   * "_activeScrollController.position.pixels ==  _activeScrollController.position.maxScrollExtent"
   */
  void _handleDragUpdate(DragUpdateDetails details) {
    if (_activeScrollController == _listScrollController &&
        (details.primaryDelta! < 0 &&
                _activeScrollController!.position.pixels ==
                    _activeScrollController!.position.maxScrollExtent ||
            details.primaryDelta! > 0 &&
                _activeScrollController!.position.pixels ==
                    _activeScrollController!.position.minScrollExtent)) {
      _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: [
          Center(child: Text('Page 1')),
          ListView(
            controller: _listScrollController,
            physics: const NeverScrollableScrollPhysics(),
            children: List.generate(
              20,
              (int index) {
                return ListTile(title: Text('Item $index'));
              },
            ),
          ),
          Center(child: Text('Page 2')),
        ],
      ),
    );
  }
}

Error place

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
ZHEN FU
  • 13
  • 2

1 Answers1

0

findRenderObject() returns nullable RenderObject?

you can check RenderBox-class

RenderBox extends RenderObject

You can do like

final RenderBox? renderBox = _listScrollController!
    .position.context.storageContext
    .findRenderObject() as RenderBox?;
 if (renderBox!.paintBounds ....

Check null before using it.

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56