Repository: flutter
Issue: New ScrollPhysics type for PageView: support page locking
Labels: framework,f: material design,f: scrolling,c: proposal,P3,team-design,triaged-design

<!-- Thank you for using Flutter!

     If you are looking for support, please check out our documentation
     or consider asking a question on Stack Overflow:
      * https://flutter.dev/
      * https://api.flutter.dev/
      * https://stackoverflow.com/questions/tagged/flutter?sort=frequent

     If you have found a bug or if our documentation doesn't have an answer
     to what you're looking for, then fill out the template below. Please read
     our guide to filing a bug first: https://flutter.dev/docs/resources/bug-reports
-->

## Use case

<!--
     Please tell us the problem you are running into that led to you wanting
     a new feature.

     Is your feature request related to a problem? Please give a clear and
     concise description of what the problem is.

     Describe the alternative solutions you've considered. Is there a package
     on pub.dev/flutter that already solves this?
-->

As a relatively common use case, an app may have a setup screen with multiple pages of setup. For example: "login", "create account", "verify phone number", "import contacts", etc. Typically, the users need to go through this setup in a well-defined, controlled way. So for example, a user shouldn't be able to navigate to the "verify phone number" page until they've logged in or signed up. The user shouldn't be able to go to the "import contacts screen" until they've verified their phone number, that sort of thing.

The standard setup for this would be to use a `PageView`. However, none of the available `ScrollPhysics` support this page locking behavior. Also, `ScrollPhysics` is immutable, which would make it hard to update which particular pages should get locked without trying to create a new physics instance.

## Proposal
Add a `PageLockingScrollPhysics` class that implements `ScrollPhysics`. 
- As an argument to the `PageLockingScrollPhysics`: `onSwipeAttempt(int fromPageIndex int toPageIndex)`. This would be called when a user tries to swipe to the left or right. The function would return `true` to allow the swipe, and `false` to deny it. 
- Alternatively, pass a list of "locks" that define a pageIndex, and a lock direction (left, right, or both). This is trickier though, because as `ScrollPhysics` is immutable, it doesn't necessarily get re-applied if the arguments change.
  - Explanation: The physics can be changed dynamically, but new physics will only take effect if the class of the provided object changes. Merely constructing a new instance with a different configuration is insufficient to cause the physics to be reapplied. (This is because the final object used is generated dynamically, which can be relatively expensive, and it would be inefficient to speculatively create this object each frame to see if the physics should be updated.)
That's why Flutter has specific ScrollPhysics like NeverScrollableScrollPhysics and AlwaysScrollableScrollPhysics.
- Other needed features:
  - When calling "animateTo()" on the `PageController`, it should ignore any page locks. As it's called programmatically, it should forcefully navigate to the desired page. In other words, `onSwipeAttempt` should not be called (or just default return true) when the swipe was initiated by "animateTo()"