Last active
April 13, 2021 15:18
-
-
Save iapicca/e8d3f3f872bc74b44d0452d830063dc6 to your computer and use it in GitHub Desktop.
focused index example
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
| import 'package:flutter/material.dart'; | |
| typedef FocusedIndexedWidgetBuilder = Widget Function( | |
| BuildContext context, int index, bool focus); | |
| final selected = ValueNotifier(0); | |
| void main() { | |
| runApp( | |
| MaterialApp( | |
| home: Material( | |
| child: Center( | |
| child: SizedBox( | |
| height: 180, | |
| child: MyWidget( | |
| focusedIndex: 2, | |
| itemCount: 5, | |
| builder: (context, index, focused) { | |
| final child = Text('$index'); | |
| return focused | |
| ? TextButton( | |
| onPressed: () => print('$index pressed'), | |
| child: child, | |
| ) | |
| : child; | |
| }, | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| class MyWidget extends StatefulWidget { | |
| final FocusedIndexedWidgetBuilder builder; | |
| final int itemCount; | |
| final int focusedIndex; | |
| final AlignmentGeometry childrenAlignment; | |
| MyWidget({ | |
| required this.itemCount, | |
| required this.builder, | |
| this.focusedIndex = 0, | |
| this.childrenAlignment = Alignment.center, | |
| }); | |
| @override | |
| _MyWidgetState createState() => _MyWidgetState(); | |
| } | |
| class _MyWidgetState extends State<MyWidget> { | |
| late final ScrollController _controller; | |
| @override | |
| void initState() { | |
| _controller = ScrollController(); | |
| super.initState(); | |
| } | |
| @override | |
| void dispose() { | |
| _controller.dispose(); | |
| super.dispose(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return LayoutBuilder( | |
| builder: (context, constraints) { | |
| final height = constraints.maxHeight / widget.itemCount; | |
| return ListView.builder( | |
| cacheExtent: 0, | |
| physics: NeverScrollableScrollPhysics(), | |
| controller: _controller, | |
| itemBuilder: (context, index) { | |
| final rem = (index - widget.focusedIndex + widget.itemCount).abs() % | |
| widget.itemCount; | |
| print('index: $index, rem: $rem'); | |
| return SizedBox( | |
| height: height, | |
| child: GestureDetector( | |
| onTap: () { | |
| print('scrolling to $rem'); | |
| selected.value = rem; | |
| _controller.animateTo( | |
| height * rem, | |
| duration: kThemeAnimationDuration, | |
| curve: Curves.fastOutSlowIn, | |
| ); | |
| }, | |
| child: ValueListenableBuilder( | |
| valueListenable: selected, | |
| builder: (context, value, child) { | |
| return Align( | |
| alignment: widget.childrenAlignment, | |
| child: | |
| widget.builder(context, rem, selected.value == rem), | |
| ); | |
| }, | |
| ), | |
| ), | |
| ); | |
| }, | |
| ); | |
| }, | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment