Skip to content

Add scrollCacheExtent to PageView#180411

Merged
auto-submit[bot] merged 15 commits into
flutter:masterfrom
koji-1009:feat/page_view_cache_extent
Mar 11, 2026
Merged

Add scrollCacheExtent to PageView#180411
auto-submit[bot] merged 15 commits into
flutter:masterfrom
koji-1009:feat/page_view_cache_extent

Conversation

@koji-1009

@koji-1009 koji-1009 commented Dec 31, 2025

Copy link
Copy Markdown
Contributor

fix #45632

Using the Xcode developer tools, I confirmed that even when scrollCacheExtent is set, allowImplicitScrolling is always respected.

movie.mov
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const PageViewDemo(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class PageViewDemo extends StatefulWidget {
  const PageViewDemo({super.key});

  @override
  State<PageViewDemo> createState() => _PageViewDemoState();
}

class _PageViewDemoState extends State<PageViewDemo> {
  int _currentIndex = 0;

  final List<
    ({
      String title,
      Axis axis,
      bool allowImplicitScrolling,
      ScrollCacheExtent scrollCacheExtent,
      IconData icon,
      String navLabel,
    })
  >
  _scenarios = [
    (
      title: 'Horizontal (allowImplicitScrolling: false)',
      axis: Axis.horizontal,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_right,
      navLabel: 'H-False',
    ),
    (
      title: 'Horizontal (allowImplicitScrolling: true)',
      axis: Axis.horizontal,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_right_alt,
      navLabel: 'H-True',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: false)',
      axis: Axis.vertical,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_down,
      navLabel: 'V-False',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: true)',
      axis: Axis.vertical,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_vertical,
      navLabel: 'V-True',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    final scenario = _scenarios[_currentIndex];

    return Scaffold(
      appBar: AppBar(title: Text(scenario.title)),
      body: PageView.builder(
        key: ValueKey('$_currentIndex'),
        scrollDirection: scenario.axis,
        allowImplicitScrolling: scenario.allowImplicitScrolling,
        scrollCacheExtent: scenario.scrollCacheExtent,
        itemCount: 10,
        itemBuilder: (context, index) => Center(
          child: Column(
            mainAxisAlignment: .center,
            children: [
              Text(
                'Page ${index + 1}',
                style: Theme.of(context).textTheme.displayLarge,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {},
                child: Text('Button ${index + 1}'),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (index) => setState(() => _currentIndex = index),
        selectedIndex: _currentIndex,
        destinations: _scenarios
            .map(
              (s) =>
                  NavigationDestination(icon: Icon(s.icon), label: s.navLabel),
            )
            .toList(),
      ),
    );
  }
}

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. labels Dec 31, 2025
@koji-1009 koji-1009 marked this pull request as ready for review December 31, 2025 22:47
@justinmc justinmc requested a review from Piinks January 13, 2026 23:31

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dug into this a bit, and it looks like PageView has always been a bit of a special case here. Typically, the scroll physics and scroll position are where allowImplicitScrolling comes from. PageView does have it's own private scroll position subclass, and physics, but I wonder if _ForceImplicitScrollPhysics is needed now with this update?

Comment thread packages/flutter/lib/src/widgets/page_view.dart Outdated
Comment thread packages/flutter/lib/src/widgets/page_view.dart
Comment thread packages/flutter/lib/src/widgets/page_view.dart
Comment thread packages/flutter/lib/src/widgets/page_view.dart Outdated
Comment thread packages/flutter/test/widgets/page_view_test.dart
@koji-1009

Copy link
Copy Markdown
Contributor Author

I apologize for the confusion. Let me clarify the scope of this PR and what tests I should add.

To clarify the scope of this PR: This PR exposes the existing cacheExtent parameter from Viewport to PageView.
This change does not affect:

  • _ForceImplicitScrollPhysics: cacheExtent controls widget pre-building in Viewport, while _ForceImplicitScrollPhysics controls accessibility semantics. These are independent mechanisms.
  • showOnScreen behavior: The showOnScreen behavior in PageView is controlled by allowImplicitScrolling (checked at L1289), not by cacheExtent.
  • _ScrollSemantics: The hasImplicitScrolling flag is controlled by allowImplicitScrolling, not by cacheExtent.

I've added a test to verify that cacheExtent does not affect the hasImplicitScrolling semantics flag. b7659a7

Please let me know if there are other tests I should add. Thank you.

@justinmc justinmc requested a review from Piinks January 27, 2026 22:58

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for the detailed explanations. I am guessing the merge conflict is coming from #181092, which deprecates all cacheExtent and cacheExtentStyle to ScrollCacheExtent.

Would you like to update this PR to use ScrollCacheExtent?

/// will traverse to the next page in the page view.
final bool allowImplicitScrolling;

/// {@macro flutter.rendering.RenderViewportBase.cacheExtent}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is some important documentation to add here regarding cacheExtent being "treated as the number of pages."

I think this is only strictly true if viewportFraction is 1.0. Since PageView uses CacheExtentStyle.viewport, the value actually represents "number of viewport lengths." If a user has viewportFraction: 0.5 (two pages per viewport), then cacheExtent: 1.0 will actually cache two additional pages, is that right?

@koji-1009 koji-1009 Feb 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the PR to use ScrollCacheExtent and updated the dartdoc accordingly.
It seems that using ScrollCacheExtent resolves the ambiguity regarding whether the value represents pages or pixels.
Could you take a look? Thanks! 8a47c54

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh man, thank you so much for updating this to the new API!

Comment thread packages/flutter/test/widgets/page_view_test.dart Outdated
@koji-1009 koji-1009 requested a review from Piinks February 13, 2026 07:44

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, thank you again! cc @chunhtai for a second review, who just introduced the ScrollCacheExtent API

@Piinks Piinks requested a review from chunhtai February 19, 2026 18:59
this.padEnds = true,
}) : childrenDelegate = SliverChildListDelegate(children);
}) : assert(
!allowImplicitScrolling || (scrollCacheExtent?.value ?? 1.0) > 0.0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider give it it default in either in initializer or in constructor body, and make it non null

markNeedsLayout();
}

/// Whether the user can traverse to the hidden pages.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should mention this is for assistive technologies such as screen readers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also consider use {@template to copy some doc from PageView.allowImplicitScrolling


/// Whether the user can traverse to the hidden pages.
///
/// If set to false, the hidden pages are excluded from the semantics tree.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence is implementation detail.

/// {@macro flutter.widgets.SliverMultiBoxAdaptorWidget.delegate}
final SliverChildDelegate delegate;

/// Controls whether the widget's children will respond to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use {@template to dedup from the PageView's doc

@justinmc justinmc requested review from Piinks and chunhtai February 24, 2026 23:11
/// This is typically used by assistive technologies, such as screen readers.
bool get allowImplicitScrolling => _allowImplicitScrolling;
bool _allowImplicitScrolling;
set allowImplicitScrolling(bool value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious why we need allowImplicitScrolling if we can control this by setting cacheextent? it feels to me allowImplicitScrolling is not too useful in the first place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review.

I'd like to share some points about the relationship between allowImplicitScrolling and scrollCacheExtent.

To unify them in PageView, we would need to enforce: if allowImplicitScrolling is false, scrollCacheExtent must be 0. And if true, it must be greater than 0.
Also, allowImplicitScrolling affects not only semantics filtering in RenderSliverFillViewport.visitChildrenForSemantics, but also showOnScreen behavior through _ForceImplicitScrollPhysics.
So scrollCacheExtent alone cannot replace allowImplicitScrolling.

This PR was focused on exposing scrollCacheExtent to PageView.
Do you think we should also change the behavior so that allowImplicitScrolling is determined by scrollCacheExtent value?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly worry about cases allowImplicitScrolling = false but scrollCacheExtent >0.

Or basically just why would one want to disable allowImplicitScrolling in the first place.

It is probably too late to remove it i n PageView, but I think we could let allowImplicitScrolling to determine by scrollCacheExtent here. WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chunhtai
Thank you for the comment.

I think we have two options here:

  1. Assert only
    • Add assertion to prevent allowImplicitScrolling = false with scrollCacheExtent.value > 0.
    • But assertions are stripped in release builds, so this does not guarantee consistency in production.
    • The current implementation is close to this approach.
  2. Runtime derivation
    • Ignore allowImplicitScrolling parameter and derive it from scrollCacheExtent.value > 0 at runtime.
    • This is safe in release builds, but scrollCacheExtent would take priority over allowImplicitScrolling — setting scrollCacheExtent > 0 would enable implicit scrolling regardless of allowImplicitScrolling = false.

Which approach do you prefer? If you think option 2 is the right direction, I can update the implementation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it a bit more, I think adding assert should probably be fine, let's go for option 1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chunhtai
Thank you for the clarification. I unified the assertions into a single one that enforces consistency between scrollCacheExtent and allowImplicitScrolling in both directions:

assert(
  scrollCacheExtent == null || (scrollCacheExtent.value > 0.0) == allowImplicitScrolling,
);

Updated in 74f979a, 8d42d7b and 8031d8a.

/// With this flag set to true, when accessibility focus reaches the end of
/// the current page and user attempts to move it to the next element, focus
/// will traverse to the next page in the page view.
/// {@endtemplate}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is false, does the ScrollCacheExtent matter anymore?

@Piinks Piinks requested a review from chunhtai March 2, 2026 20:53
@koji-1009 koji-1009 changed the title Add cacheExtent to PageView Add scrollCacheExtent to PageView Mar 6, 2026

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chunhtai chunhtai added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 6, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Mar 6, 2026
@auto-submit

auto-submit Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/180411, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as well!

@Piinks Piinks self-assigned this Mar 6, 2026
@chunhtai chunhtai added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 11, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue Mar 11, 2026
Merged via the queue into flutter:master with commit 14d21ce Mar 11, 2026
76 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Mar 11, 2026
@koji-1009 koji-1009 deleted the feat/page_view_cache_extent branch March 11, 2026 22:39
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 12, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 12, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 12, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 12, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Mar 12, 2026
flutter/flutter@3f400d7...9e36adb

2026-03-12 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from QD887D4OanteB7UKM... to jJbpv4J_tjW-wuKDq... (flutter/flutter#183584)
2026-03-12 matt.kosarek@canonical.com Adding the SatelliteWindowController interface to `_window.dart` (flutter/flutter#182903)
2026-03-12 engine-flutter-autoroll@skia.org Roll Skia from 0cab3e4ee34b to 46f41493ebf4 (17 revisions) (flutter/flutter#183553)
2026-03-12 engine-flutter-autoroll@skia.org Roll Dart SDK from 8531f7c2bdae to 59be21f25f2d (4 revisions) (flutter/flutter#183547)
2026-03-12 koji.wakamiya@gmail.com [ios][engine] Fix keyboard flicker when switching text fields (flutter/flutter#182661)
2026-03-11 34871572+gmackall@users.noreply.github.com Rename hcpp opt in flag to `enable-hcpp` (flutter/flutter#183151)
2026-03-11 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#183541)
2026-03-11 97480502+b-luk@users.noreply.github.com Re-enable gpu_test.dart for opengles, but disable specific tests in the file (flutter/flutter#183531)
2026-03-11 jacksongardner@google.com Use CLA-approved email and username for github workflow commits. (flutter/flutter#183540)
2026-03-11 okorohelijah@google.com [integration_test]UIScene Migration (flutter/flutter#182631)
2026-03-11 git@reb0.org ci: Run orchestrator for windows_arm_host_engine on Linux  (flutter/flutter#181075)
2026-03-11 mdebbar@google.com [web] Prevent Firefox auto-updates (flutter/flutter#183330)
2026-03-11 koji.wakamiya@gmail.com Add scrollCacheExtent to PageView (flutter/flutter#180411)
2026-03-11 danny@tuppeny.com Remove redundant VS Code code/tests (flutter/flutter#183506)
2026-03-11 danny@tuppeny.com Roll pub packages (flutter/flutter#183527)
2026-03-11 34871572+gmackall@users.noreply.github.com Reapply "Make HCPP upgrading work for vd/tlhc (#181024)" (#183310) (flutter/flutter#183360)
2026-03-11 victorsanniay@gmail.com Add awaits to dev/ callsites (flutter/flutter#183479)
2026-03-11 stuartmorgan@google.com Standardize review timeline guidance (flutter/flutter#183465)
2026-03-11 chingjun@google.com Rename ExecutionModelToString to ExecutionModelToStringName. (flutter/flutter#183461)
2026-03-11 34871572+gmackall@users.noreply.github.com Fix input mirroring in platform views when system language is RTL, and support is set in manifest. (flutter/flutter#183472)
2026-03-11 engine-flutter-autoroll@skia.org Roll Packages from ee460d6 to ecace66 (10 revisions) (flutter/flutter#183517)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
okorohelijah pushed a commit to okorohelijah/packages that referenced this pull request Mar 26, 2026
…r#11233)

flutter/flutter@3f400d7...9e36adb

2026-03-12 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from QD887D4OanteB7UKM... to jJbpv4J_tjW-wuKDq... (flutter/flutter#183584)
2026-03-12 matt.kosarek@canonical.com Adding the SatelliteWindowController interface to `_window.dart` (flutter/flutter#182903)
2026-03-12 engine-flutter-autoroll@skia.org Roll Skia from 0cab3e4ee34b to 46f41493ebf4 (17 revisions) (flutter/flutter#183553)
2026-03-12 engine-flutter-autoroll@skia.org Roll Dart SDK from 8531f7c2bdae to 59be21f25f2d (4 revisions) (flutter/flutter#183547)
2026-03-12 koji.wakamiya@gmail.com [ios][engine] Fix keyboard flicker when switching text fields (flutter/flutter#182661)
2026-03-11 34871572+gmackall@users.noreply.github.com Rename hcpp opt in flag to `enable-hcpp` (flutter/flutter#183151)
2026-03-11 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#183541)
2026-03-11 97480502+b-luk@users.noreply.github.com Re-enable gpu_test.dart for opengles, but disable specific tests in the file (flutter/flutter#183531)
2026-03-11 jacksongardner@google.com Use CLA-approved email and username for github workflow commits. (flutter/flutter#183540)
2026-03-11 okorohelijah@google.com [integration_test]UIScene Migration (flutter/flutter#182631)
2026-03-11 git@reb0.org ci: Run orchestrator for windows_arm_host_engine on Linux  (flutter/flutter#181075)
2026-03-11 mdebbar@google.com [web] Prevent Firefox auto-updates (flutter/flutter#183330)
2026-03-11 koji.wakamiya@gmail.com Add scrollCacheExtent to PageView (flutter/flutter#180411)
2026-03-11 danny@tuppeny.com Remove redundant VS Code code/tests (flutter/flutter#183506)
2026-03-11 danny@tuppeny.com Roll pub packages (flutter/flutter#183527)
2026-03-11 34871572+gmackall@users.noreply.github.com Reapply "Make HCPP upgrading work for vd/tlhc (#181024)" (#183310) (flutter/flutter#183360)
2026-03-11 victorsanniay@gmail.com Add awaits to dev/ callsites (flutter/flutter#183479)
2026-03-11 stuartmorgan@google.com Standardize review timeline guidance (flutter/flutter#183465)
2026-03-11 chingjun@google.com Rename ExecutionModelToString to ExecutionModelToStringName. (flutter/flutter#183461)
2026-03-11 34871572+gmackall@users.noreply.github.com Fix input mirroring in platform views when system language is RTL, and support is set in manifest. (flutter/flutter#183472)
2026-03-11 engine-flutter-autoroll@skia.org Roll Packages from ee460d6 to ecace66 (10 revisions) (flutter/flutter#183517)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
mboetger pushed a commit to mboetger/flutter that referenced this pull request Mar 26, 2026
fix flutter#45632

Using the Xcode developer tools, I confirmed that even when
`scrollCacheExtent` is set, `allowImplicitScrolling` is always
respected.


https://github.com/user-attachments/assets/4f99875d-05f9-4224-a203-5b1d9274f7c9

```dart
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const PageViewDemo(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class PageViewDemo extends StatefulWidget {
  const PageViewDemo({super.key});

  @OverRide
  State<PageViewDemo> createState() => _PageViewDemoState();
}

class _PageViewDemoState extends State<PageViewDemo> {
  int _currentIndex = 0;

  final List<
    ({
      String title,
      Axis axis,
      bool allowImplicitScrolling,
      ScrollCacheExtent scrollCacheExtent,
      IconData icon,
      String navLabel,
    })
  >
  _scenarios = [
    (
      title: 'Horizontal (allowImplicitScrolling: false)',
      axis: Axis.horizontal,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_right,
      navLabel: 'H-False',
    ),
    (
      title: 'Horizontal (allowImplicitScrolling: true)',
      axis: Axis.horizontal,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_right_alt,
      navLabel: 'H-True',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: false)',
      axis: Axis.vertical,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_down,
      navLabel: 'V-False',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: true)',
      axis: Axis.vertical,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_vertical,
      navLabel: 'V-True',
    ),
  ];

  @OverRide
  Widget build(BuildContext context) {
    final scenario = _scenarios[_currentIndex];

    return Scaffold(
      appBar: AppBar(title: Text(scenario.title)),
      body: PageView.builder(
        key: ValueKey('$_currentIndex'),
        scrollDirection: scenario.axis,
        allowImplicitScrolling: scenario.allowImplicitScrolling,
        scrollCacheExtent: scenario.scrollCacheExtent,
        itemCount: 10,
        itemBuilder: (context, index) => Center(
          child: Column(
            mainAxisAlignment: .center,
            children: [
              Text(
                'Page ${index + 1}',
                style: Theme.of(context).textTheme.displayLarge,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {},
                child: Text('Button ${index + 1}'),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (index) => setState(() => _currentIndex = index),
        selectedIndex: _currentIndex,
        destinations: _scenarios
            .map(
              (s) =>
                  NavigationDestination(icon: Icon(s.icon), label: s.navLabel),
            )
            .toList(),
      ),
    );
  }
}
```

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
ahmedsameha1 pushed a commit to ahmedsameha1/flutter that referenced this pull request Apr 14, 2026
fix flutter#45632

Using the Xcode developer tools, I confirmed that even when
`scrollCacheExtent` is set, `allowImplicitScrolling` is always
respected.


https://github.com/user-attachments/assets/4f99875d-05f9-4224-a203-5b1d9274f7c9

```dart
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const PageViewDemo(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class PageViewDemo extends StatefulWidget {
  const PageViewDemo({super.key});

  @OverRide
  State<PageViewDemo> createState() => _PageViewDemoState();
}

class _PageViewDemoState extends State<PageViewDemo> {
  int _currentIndex = 0;

  final List<
    ({
      String title,
      Axis axis,
      bool allowImplicitScrolling,
      ScrollCacheExtent scrollCacheExtent,
      IconData icon,
      String navLabel,
    })
  >
  _scenarios = [
    (
      title: 'Horizontal (allowImplicitScrolling: false)',
      axis: Axis.horizontal,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_right,
      navLabel: 'H-False',
    ),
    (
      title: 'Horizontal (allowImplicitScrolling: true)',
      axis: Axis.horizontal,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_right_alt,
      navLabel: 'H-True',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: false)',
      axis: Axis.vertical,
      allowImplicitScrolling: false,
      scrollCacheExtent: ScrollCacheExtent.viewport(0),
      icon: Icons.swipe_down,
      navLabel: 'V-False',
    ),
    (
      title: 'Vertical (allowImplicitScrolling: true)',
      axis: Axis.vertical,
      allowImplicitScrolling: true,
      scrollCacheExtent: ScrollCacheExtent.viewport(5),
      icon: Icons.swipe_vertical,
      navLabel: 'V-True',
    ),
  ];

  @OverRide
  Widget build(BuildContext context) {
    final scenario = _scenarios[_currentIndex];

    return Scaffold(
      appBar: AppBar(title: Text(scenario.title)),
      body: PageView.builder(
        key: ValueKey('$_currentIndex'),
        scrollDirection: scenario.axis,
        allowImplicitScrolling: scenario.allowImplicitScrolling,
        scrollCacheExtent: scenario.scrollCacheExtent,
        itemCount: 10,
        itemBuilder: (context, index) => Center(
          child: Column(
            mainAxisAlignment: .center,
            children: [
              Text(
                'Page ${index + 1}',
                style: Theme.of(context).textTheme.displayLarge,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {},
                child: Text('Button ${index + 1}'),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (index) => setState(() => _currentIndex = index),
        selectedIndex: _currentIndex,
        destinations: _scenarios
            .map(
              (s) =>
                  NavigationDestination(icon: Icon(s.icon), label: s.navLabel),
            )
            .toList(),
      ),
    );
  }
}
```

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11233)

flutter/flutter@3f400d7...9e36adb

2026-03-12 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from QD887D4OanteB7UKM... to jJbpv4J_tjW-wuKDq... (flutter/flutter#183584)
2026-03-12 matt.kosarek@canonical.com Adding the SatelliteWindowController interface to `_window.dart` (flutter/flutter#182903)
2026-03-12 engine-flutter-autoroll@skia.org Roll Skia from 0cab3e4ee34b to 46f41493ebf4 (17 revisions) (flutter/flutter#183553)
2026-03-12 engine-flutter-autoroll@skia.org Roll Dart SDK from 8531f7c2bdae to 59be21f25f2d (4 revisions) (flutter/flutter#183547)
2026-03-12 koji.wakamiya@gmail.com [ios][engine] Fix keyboard flicker when switching text fields (flutter/flutter#182661)
2026-03-11 34871572+gmackall@users.noreply.github.com Rename hcpp opt in flag to `enable-hcpp` (flutter/flutter#183151)
2026-03-11 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#183541)
2026-03-11 97480502+b-luk@users.noreply.github.com Re-enable gpu_test.dart for opengles, but disable specific tests in the file (flutter/flutter#183531)
2026-03-11 jacksongardner@google.com Use CLA-approved email and username for github workflow commits. (flutter/flutter#183540)
2026-03-11 okorohelijah@google.com [integration_test]UIScene Migration (flutter/flutter#182631)
2026-03-11 git@reb0.org ci: Run orchestrator for windows_arm_host_engine on Linux  (flutter/flutter#181075)
2026-03-11 mdebbar@google.com [web] Prevent Firefox auto-updates (flutter/flutter#183330)
2026-03-11 koji.wakamiya@gmail.com Add scrollCacheExtent to PageView (flutter/flutter#180411)
2026-03-11 danny@tuppeny.com Remove redundant VS Code code/tests (flutter/flutter#183506)
2026-03-11 danny@tuppeny.com Roll pub packages (flutter/flutter#183527)
2026-03-11 34871572+gmackall@users.noreply.github.com Reapply "Make HCPP upgrading work for vd/tlhc (#181024)" (#183310) (flutter/flutter#183360)
2026-03-11 victorsanniay@gmail.com Add awaits to dev/ callsites (flutter/flutter#183479)
2026-03-11 stuartmorgan@google.com Standardize review timeline guidance (flutter/flutter#183465)
2026-03-11 chingjun@google.com Rename ExecutionModelToString to ExecutionModelToStringName. (flutter/flutter#183461)
2026-03-11 34871572+gmackall@users.noreply.github.com Fix input mirroring in platform views when system language is RTL, and support is set in manifest. (flutter/flutter#183472)
2026-03-11 engine-flutter-autoroll@skia.org Roll Packages from ee460d6 to ecace66 (10 revisions) (flutter/flutter#183517)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.

Projects

Development

Successfully merging this pull request may close these issues.

Allow PageView to set a cacheExtent

3 participants