Created
August 1, 2021 23:14
-
-
Save monkeyswarm/427f72b80f8199c6b99f2799269969cc to your computer and use it in GitHub Desktop.
Track containers 2: page view with dynamic viewportFraction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// subclass pagecontroller for variable viewportfraction. | |
// kind of works, gets weird for bottom one, paging gets wierd. | |
import 'dart:math'; | |
import 'package:flutter/material.dart'; | |
void main() => runApp(MyApp()); | |
class CustomPageController extends PageController { | |
double _viewportFraction = .5; | |
CustomPageController() : super(initialPage: 1); | |
double get viewportFraction => _viewportFraction; | |
set viewportFraction(double v) => _viewportFraction = v; | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: MyHomePage(title: 'Flutter Demo Home Page'), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
final String title; | |
MyHomePage({Key? key, required this.title}) : super(key: key); | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
late ValueNotifier<double> _viewportNotifier; | |
late CustomPageController _pageController; | |
@override | |
void initState() { | |
super.initState(); | |
_pageController = CustomPageController()..addListener(_onPageScroll); | |
_viewportNotifier = ValueNotifier<double>(.5); | |
} | |
double _scale(double value, double inLow, double inHigh, double outLow, | |
double outHigh) { | |
return (((value - inLow) / (inHigh - inLow)) * (outHigh - outLow) + | |
outLow).clamp(min(outLow, outHigh), max(outLow, outHigh)); | |
} | |
void _onPageScroll() { | |
final offset = _pageController.position.pixels; | |
var newViewportFraction; | |
if (offset < 300) { | |
newViewportFraction = _scale(offset, 0, 300, 1.0, .5); | |
} else if (offset > 300) { | |
newViewportFraction = _scale(offset, 300, 600, .5, 1.0); | |
} else { | |
newViewportFraction = .5; | |
} | |
// print('offset $offset, newViewportFraction $newViewportFraction'); | |
_pageController.viewportFraction = newViewportFraction; | |
_viewportNotifier.value = newViewportFraction; | |
} | |
Widget _buildContainer(Color color, Color borderColor) => Container( | |
decoration: BoxDecoration( | |
color: color, border: Border.all(color: borderColor, width: 8)), | |
child: | |
Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ | |
RaisedButton(onPressed: () {}, child: Text('foo')), | |
RaisedButton(onPressed: () {}, child: Text('foo')), | |
RaisedButton(onPressed: () {}, child: Text('foo')), | |
])); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text(widget.title), | |
), | |
body: Column(children: [ | |
Container( | |
color: Color(0x88888888), | |
height: 600, | |
child: AnimatedBuilder( | |
animation: _viewportNotifier, | |
builder: (_, __) => PageView( | |
scrollDirection: Axis.vertical, | |
controller: _pageController, | |
children: [ | |
_buildContainer( | |
Color(0x88FF0000), Color(0xFFFF0000)), | |
Container(color: Color(0x8800FF00)), | |
_buildContainer( | |
Color(0x880000FF), Color(0xFF0000FF)), | |
]))), | |
])); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment