Skip to content

Scrollable.ensureVisible does not work with nested SingleChildScrollViews on both axes #65100

@orischwartz

Description

@orischwartz

Steps to Reproduce

  1. Run the sample app below. It creates a grid of cells using a Column of Rows and two SingleChildScrollViews--one for Axis.horizontal and the other for Axis.vertical.

image

Expected results:
Tapping any cell should center that cell in the viewport via ensureVisible.

         Scrollable.ensureVisible(context,
            alignment: .5,
            duration: Duration(
              milliseconds: 500,
            ));

Actual results:
Cells are not centered as expected. This works correctly when using just a single SingleChildScrollView but not with two.

ensureVisible does traverse all the Scrollables in the context:

ScrollableState scrollable = Scrollable.of(context);
while (scrollable != null) {
futures.add(scrollable.position.ensureVisible(
context.findRenderObject(),
alignment: alignment,
duration: duration,
curve: curve,
alignmentPolicy: alignmentPolicy,
));
context = scrollable.context;
scrollable = Scrollable.of(context);
}

But something about nesting the scrollviews will yield different values here:

RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect }) {

This behavior has been present since 2019 and is reproducible on the latest beta branch on both iOS and Android.

import 'package:flutter/material.dart';

void main() async {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: Grid(),
      ),
    ),
  );
}

class Grid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    List<Row> rows = List.generate(
      15,
      (y) => Row(
        children: List.generate(
          12,
          (x) => Cell(
            child: Text("$x,$y"),
          ),
        ),
      ),
    );

    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Column(
          children: rows,
        ),
      ),
    );
  }
}

class Cell extends StatelessWidget {
  final Widget child;

  const Cell({
    this.child,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        Scrollable.ensureVisible(context,
            alignment: .5,
            duration: Duration(
              milliseconds: 500,
            ));
      },
      child: Container(
        width: 100,
        height: 100,
        color: Colors.grey.withOpacity(.2),
        margin: EdgeInsets.all(3),
        child: Center(
          child: child,
        ),
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    f: scrollingViewports, list views, slivers, etc.found in release: 1.22Found to occur in 1.22frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions