-
-
Save andrzejchm/02c1728b6f31a69fde2fb4e10b636060 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart'; | |
class ExpandablePageView extends StatefulWidget { | |
final List<Widget> children; | |
const ExpandablePageView({ | |
Key key, | |
@required this.children, | |
}) : super(key: key); | |
@override | |
_ExpandablePageViewState createState() => _ExpandablePageViewState(); | |
} | |
class _ExpandablePageViewState extends State<ExpandablePageView> with TickerProviderStateMixin { | |
PageController _pageController; | |
List<double> _heights; | |
int _currentPage = 0; | |
double get _currentHeight => _heights[_currentPage]; | |
@override | |
void initState() { | |
_heights = widget.children.map((e) => 0.0).toList(); | |
super.initState(); | |
_pageController = PageController() // | |
..addListener(() { | |
final _newPage = _pageController.page.round(); | |
if (_currentPage != _newPage) { | |
setState(() => _currentPage = _newPage); | |
} | |
}); | |
} | |
@override | |
void dispose() { | |
_pageController.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return TweenAnimationBuilder<double>( | |
curve: Curves.easeInOutCubic, | |
duration: const Duration(milliseconds: 100), | |
tween: Tween<double>(begin: _heights[0], end: _currentHeight), | |
builder: (context, value, child) => SizedBox(height: value, child: child), | |
child: PageView( | |
controller: _pageController, | |
children: _sizeReportingChildren, | |
), | |
); | |
} | |
List<Widget> get _sizeReportingChildren => widget.children | |
.asMap() // | |
.map( | |
(index, child) => MapEntry( | |
index, | |
OverflowBox( | |
//needed, so that parent won't impose its constraints on the children, thus skewing the measurement results. | |
minHeight: 0, | |
maxHeight: double.infinity, | |
alignment: Alignment.topCenter, | |
child: SizeReportingWidget( | |
onSizeChange: (size) => setState(() => _heights[index] = size?.height ?? 0), | |
child: child, | |
), | |
), | |
), | |
) | |
.values | |
.toList(); | |
} | |
class SizeReportingWidget extends StatefulWidget { | |
final Widget child; | |
final ValueChanged<Size> onSizeChange; | |
const SizeReportingWidget({ | |
Key key, | |
@required this.child, | |
@required this.onSizeChange, | |
}) : super(key: key); | |
@override | |
_SizeReportingWidgetState createState() => _SizeReportingWidgetState(); | |
} | |
class _SizeReportingWidgetState extends State<SizeReportingWidget> { | |
Size _oldSize; | |
@override | |
Widget build(BuildContext context) { | |
WidgetsBinding.instance.addPostFrameCallback((_) => _notifySize()); | |
return widget.child; | |
} | |
void _notifySize() { | |
final size = context?.size; | |
if (_oldSize != size) { | |
_oldSize = size; | |
widget.onSizeChange(size); | |
} | |
} | |
} |
By permission from @andrzejchm I created a package from that code: expandable_page_view
@proninyaroslav I would be really grateful if You could create an issue or even open a pull request with suggested change for that package.
I thought that people would be more interested in just including the package name in pubspec.yaml, rather than copy and paste the code inside their projects. I also hope it will be improved in the future and found bugs will be fixed (as the one You found).
Thanks for the library. It is working a treat!
@jeremylcarter Thanks for important package. I am facing issue when i change page it will refresh whole parent widget. So to avoid that is there any way.
@jeremylcarter Thanks for important package. I am facing issue when i change page it will refresh whole parent widget. So to avoid that is there any way.
@fitterfly-bimal
this gist is not about the library, for any library-related questions please reach out directly at https://github.com/Limbou/expandable_page_view
Big thanks to @andrzejchm and @Limbou . You are awesome!
Which widget to use to put that ExpandablePageView inside, cause if I don't put height to parent container, Height of that PageView becomes 0