expandable_container.dart 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import 'package:flutter/material.dart';
  2. /// 可伸缩容器
  3. class ExpandableContainer extends StatefulWidget {
  4. final Widget child;
  5. final bool expanded;
  6. final double collapsedHeight;
  7. final double expandedHeight;
  8. final double fixedWidth;
  9. ExpandableContainer({
  10. required this.child,
  11. this.expanded = false,
  12. this.collapsedHeight = 40.0,
  13. this.expandedHeight = 200.0,
  14. this.fixedWidth = 250.0,
  15. });
  16. @override
  17. _ExpandableContainerState createState() => _ExpandableContainerState();
  18. }
  19. class _ExpandableContainerState extends State<ExpandableContainer>
  20. with SingleTickerProviderStateMixin {
  21. late AnimationController _controller;
  22. late Animation<double> _heightFactor;
  23. @override
  24. void initState() {
  25. super.initState();
  26. _controller = AnimationController(
  27. vsync: this,
  28. duration: Duration(milliseconds: 500),
  29. );
  30. final double initialHeightFactor = widget.expanded ? 1.0 : 0.0;
  31. _heightFactor = _controller
  32. .drive(
  33. CurveTween(curve: Curves.fastOutSlowIn),
  34. )
  35. .drive(
  36. Tween<double>(begin: initialHeightFactor, end: 1.0),
  37. );
  38. if (widget.expanded) {
  39. _controller.value = 1.0;
  40. }
  41. }
  42. @override
  43. void didUpdateWidget(ExpandableContainer oldWidget) {
  44. super.didUpdateWidget(oldWidget);
  45. if (widget.expanded != oldWidget.expanded) {
  46. if (widget.expanded) {
  47. _controller.forward();
  48. } else {
  49. _controller.reverse();
  50. }
  51. }
  52. }
  53. @override
  54. void dispose() {
  55. _controller.dispose();
  56. super.dispose();
  57. }
  58. void _toggleExpanded() {
  59. print("toggleExpanded");
  60. if (_controller.isAnimating) {
  61. return;
  62. }
  63. final bool isExpanded = _heightFactor.value == 1.0;
  64. _controller.fling(
  65. velocity: isExpanded ? -2.0 : 2.0,
  66. );
  67. }
  68. @override
  69. Widget build(BuildContext context) {
  70. return GestureDetector(
  71. behavior: HitTestBehavior.opaque,
  72. onTap: _toggleExpanded,
  73. child: AnimatedSize(
  74. duration: Duration(milliseconds: 500),
  75. child: AnimatedBuilder(
  76. animation: _heightFactor,
  77. builder: (BuildContext context, Widget? child) {
  78. return Container(
  79. width: widget.fixedWidth,
  80. height: widget.collapsedHeight +
  81. (_heightFactor.value *
  82. (widget.expandedHeight - widget.collapsedHeight)),
  83. child: child,
  84. );
  85. },
  86. child: widget.child,
  87. ),
  88. ),
  89. );
  90. }
  91. }