Skip to content

Instantly share code, notes, and snippets.

@monkeyswarm
Created August 1, 2021 23:14
Show Gist options
  • Save monkeyswarm/427f72b80f8199c6b99f2799269969cc to your computer and use it in GitHub Desktop.
Save monkeyswarm/427f72b80f8199c6b99f2799269969cc to your computer and use it in GitHub Desktop.
Track containers 2: page view with dynamic viewportFraction
// 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