-
-
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).
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
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!
@andrzejchm
Fixed version of
SizeReportingWidget
(credit: https://github.com/fluttercommunity/backdrop/blob/d4e10a5547a192052731992285bc9b2625f277b0/lib/scaffold.dart#L608). The previous one didn't work with dynamic widgets likeExpandableListTile
. After expanding, thePageView
height didn't resize.An example that reproduces the problem: