Flutter横向展开组件关闭时溢出问题求助及实现方案咨询
Flutter横向展开组件布局溢出问题
我正在开发横向展开组件,需求如下:
- 初始状态下两个Widget平分一行空间
- 点击任意组件时,该组件展开,另一个组件隐藏
- 当前关闭展开的组件时,出现布局溢出问题
尝试过的方案:
- 考虑使用Hero Widget,但不清楚如何在不跳转路由的场景下实现
- 可以通过Builder实现动画,但该方式过于繁琐,不够便捷
相关代码:
import 'package:flutter/material.dart'; void main() { runApp(const AccountSecurityPage()); } class AccountSecurityPage extends StatefulWidget { const AccountSecurityPage({super.key}); @override State<AccountSecurityPage> createState() => _AccountSecurityPageState(); } enum SelectedField { email, psw } class _AccountSecurityPageState extends State<AccountSecurityPage> { SelectedField? field; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.white, appBar: AppBar(title: const Text("Account Security")), body: Column( children: [ const Column( children: [ Row( children: [ Text( "Two-factor authentication", style: TextStyle(fontWeight: FontWeight.w700), ), ], ), Wrap( children: [ Text( "To protect your account, we recommend enabling at least one type of two-factor authentication") ], ) ], ), Row( mainAxisSize: MainAxisSize.max, children: [ //SliderAppScreen(), HorizontalExpandedField<SelectedField>( value: SelectedField.email, groupValue: field, onChanged: (SelectedField? val) { if (field != SelectedField.email) { setState(() { field = SelectedField.email; }); } else { setState(() { field = null; }); } }, ), HorizontalExpandedField<SelectedField>( value: SelectedField.psw, groupValue: field, onChanged: (SelectedField? val) { if (field != SelectedField.psw) { setState(() { field = SelectedField.psw; }); } else { setState(() { field = null; }); } }, ), ], ) ], ), ), ); } } class HorizontalExpandedField<T> extends StatefulWidget { final T value; final T? groupValue; final ValueChanged<T?> onChanged; const HorizontalExpandedField({ super.key, required this.value, required this.groupValue, required this.onChanged, }); @override State<HorizontalExpandedField<T>> createState() => _HorizontalExpandedFieldState(); } class _HorizontalExpandedFieldState<T> extends State<HorizontalExpandedField<T>> with TickerProviderStateMixin { late final AnimationController _expandedController; late final AnimationController _scaleContainerController; late Animation _expandedAnimation; late final Animation<double> _scaleContainerAnimation; @override initState() { _scaleContainerController = AnimationController( duration: const Duration(milliseconds: 200), vsync: this); _scaleContainerAnimation = CurvedAnimation( parent: Tween<double>(begin: 0.0, end: 1).animate(_scaleContainerController), curve: Curves.easeOut, ); super.initState(); _expandedController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this); _expandedAnimation = IntTween(begin: 1, end: 20).animate(_expandedController); _expandedAnimation.addListener(() => setState(() {})); _scaleContainerController.addListener(() => setState(() {})); } @override dispose() { _scaleContainerController.dispose(); _expandedController.dispose(); super.dispose(); } void _handleChanged(bool selected) { if (!selected) { _expandedController .forward() .then((value) => _scaleContainerController.forward()); widget.onChanged(widget.value); } else { if (!isCollapse) { _scaleContainerController .reverse() .then((value) => _expandedController.reverse()); } widget.onChanged(null); } return; } bool get _isSelected => widget.value == widget.groupValue; bool get isCollapse => !_isSelected && widget.groupValue != null; @override Widget build(BuildContext context) { return Expanded( flex: _expandedAnimation.value, child: Padding( padding: const EdgeInsets.all(8.0), child: MaterialButton( clipBehavior: Clip.hardEdge, onPressed: () { _handleChanged(_isSelected); }, color: const Color(0xFFF8F8F8), elevation: 0, padding: const EdgeInsets.all(16), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: _isSelected ? CrossAxisAlignment.start : CrossAxisAlignment.center, children: [ Expanded( child: Flex( clipBehavior: Clip.hardEdge, direction: _isSelected ? Axis.horizontal : Axis.vertical, crossAxisAlignment: CrossAxisAlignment.center, children: const <Widget>[ Icon(Icons.email_rounded), Text(softWrap: false, "email"), ], ), ), const Expanded(child: Icon(Icons.expand_circle_down)), ], ), //if (_isSelected && !isCollapse) ScaleTransition( scale: _scaleContainerAnimation, alignment: Alignment.centerLeft, child: Container( decoration: const BoxDecoration( color: Colors.red, ), clipBehavior: Clip.hardEdge, height: _scaleContainerAnimation.value * 50, width: double.infinity, child: Column( children: [ Expanded( child: Row( children: [ Text(softWrap: false, "email"), Expanded(child: TextField()), ], ), ), ], ), ), ) ], ), ), ), ); } }
内容的提问来源于stack exchange,提问作者kannt_im
相关产品推荐
相关产品推荐

