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

Scroll to index in nested CustomScrollView #22

Open
ovidiu-anghelina opened this issue Feb 13, 2020 · 4 comments
Open

Scroll to index in nested CustomScrollView #22

ovidiu-anghelina opened this issue Feb 13, 2020 · 4 comments

Comments

@ovidiu-anghelina
Copy link

I have a custom widget that builds a CustomScrollView with form fields, with each of the form fields wrapped in AutoScrollTag. This works well on its own, when I navigate to a Route that has this custom widget as its child - I can scroll to any of the form fields and highlight them.

I have a use case where a Route has a SingleChildScrollView as its child, with a header followed by my custom widget. For this page to scroll as expected, the CustomScrollView in my custom widget is using physics: NeverScrollableScrollPhysics() and shrinkWrap: true. The problem is, scrollToIndex() no longer scrolls to the specified field in this scenario - the highlighting still works even though the field is not on the screen.

I've tried assigning an AutoScrollController to the SingleChildScrollView and using the same controller with the AutoScrollTag widgets, but that didn't make a difference.

I also tried setting the parentController of the AutoScrollController assigned to the CustomScrollView to that of the SingleChildScrollView, but that also didn't make a difference.

What is the correct way, if any, to achieve this?

@jerrywell
Copy link
Member

not quite sure what the actual case you got.
can you provide the sample code, so i can reproduce it?

@ovidiu-anghelina
Copy link
Author

ovidiu-anghelina commented Feb 14, 2020

Here it is:

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

void main() {
  runApp(MaterialApp(
    theme: ThemeData.light(),
    home: Builder(
      builder: (BuildContext context) => Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RaisedButton(
            child: const Text("Not nested - working"),
            onPressed: () {
              Navigator.of(context).push(MaterialPageRoute(
                builder: (BuildContext context) => CustomWidget(nested: false),
              ));
            },
          ),
          RaisedButton(
            child: const Text("Nested - not working"),
            onPressed: () {
              Navigator.of(context).push(MaterialPageRoute(
                builder: (BuildContext context) => CustomWidget(nested: true),
              ));
            },
          ),
        ],
      ),
    ),
  ));
}

class CustomWidget extends StatelessWidget {
  final AutoScrollController autoScrollController = AutoScrollController();
  final bool nested;

  CustomWidget({@required this.nested});

  @override
  Widget build(BuildContext context) {

    Widget body = CustomScrollView(
      controller: autoScrollController,
      physics: nested ? const NeverScrollableScrollPhysics() : null,
      shrinkWrap: nested,
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildBuilderDelegate((BuildContext context, int index) => AutoScrollTag(
            key: ValueKey(index),
            controller: autoScrollController,
            index: index,
            highlightColor: Colors.redAccent,
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 5),
              child: Container(
                height: 40,
                width: MediaQuery.of(context).size.width,
                color: index % 2 == 0 ? Colors.blueGrey : Colors.grey,
              ),
            ),
          ), childCount: 200),
        )
      ],
    );

    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.looks_one),
            onPressed: () {
              autoScrollController.scrollToIndex(50).then((_) {
                autoScrollController.highlight(50);
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.looks_two),
            onPressed: () {
              autoScrollController.scrollToIndex(100).then((_) {
                autoScrollController.highlight(100);
              });
            },
          ),
        ],
      ),
      body: SafeArea(
        child: !nested ? body : SingleChildScrollView(
          child: body,
        ),
      ),
    );
  }
}

In the actual app, there are several thousand lines of code of logic and layout within that custom widget building a CustomScrollView, which is why it's very important that I can actually nest it in another ScrollView when needed.

While the sample above doesn't make much sense on its own, it accurately replicates the relevant part of the widget hierarchy in the real app.

@rahuldange09
Copy link

Hello @jerrywell any updates on this?

@nhat108
Copy link

nhat108 commented May 10, 2020

My answer is here:
https://stackoverflow.com/a/61709995/11206617
Thanks me later!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants