1.官方折疊控件ExpansionTiles
官方默認(rèn)提供了一個折疊控件 ExpansionTiles 主要用于listView做折疊和展開操作的,先來看看一般的用法
Widget _buildTiles(Entry root) {
return new ExpansionTile(
title: new Text(root.title),
children: root.children.map(_buildTiles).toList(),
);
}
title 一般就是點擊的標(biāo)題,可以是任意的Widget
children 是折疊和展開的List<Widget>
使用很方便
2.自定義折疊控件ExpansionLayout
由于項目中的使用到的折疊控件是由外部Widget控制的肿男,涉及到一些業(yè)務(wù)邏輯赊舶,使用官方控件ExpansionTiles草姻,存在諸多不便瀑构,于是查看ExpansionTiles 笨腥,根據(jù)ExpansionTiles源碼做自己的修改目尖,主要是根據(jù)外部傳入的字段來控制展開和折疊
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
const Duration _kExpand = Duration(milliseconds: 200);
class ExpansionLayout extends StatefulWidget {
const ExpansionLayout({
Key key,
this.backgroundColor,
this.onExpansionChanged,
this.children = const <Widget>[],
this.trailing,
this.isExpanded,
}) : super(key: key);
final ValueChanged<bool> onExpansionChanged;
final List<Widget> children;
final Color backgroundColor;
//增加字段控制是否折疊
final bool isExpanded;
final Widget trailing;
@override
_ExpansionLayoutState createState() => _ExpansionLayoutState();
}
class _ExpansionLayoutState extends State<ExpansionLayout>
with SingleTickerProviderStateMixin {
//折疊展開的動畫馒吴,主要是控制height
static final Animatable<double> _easeInTween =
CurveTween(curve: Curves.easeIn);
AnimationController _controller;
Animation<double> _heightFactor;
bool _isExpanded;
@override
void initState() {
super.initState();
//初始化控制器以及出事狀態(tài)
_controller = AnimationController(duration: _kExpand, vsync: this);
_heightFactor = _controller.drive(_easeInTween);
_isExpanded = widget.isExpanded;
if (_isExpanded) _controller.value = 1.0;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _handleTap() {
setState(() {
_isExpanded = widget.isExpanded;
if (_isExpanded) {
_controller.forward();
} else {
_controller.reverse().then<void>((void value) {
if (!mounted) return;
});
}
//保存頁面數(shù)據(jù)
PageStorage.of(context)?.writeState(context, _isExpanded);
});
//回調(diào)展開事件
if (widget.onExpansionChanged != null)
widget.onExpansionChanged(_isExpanded);
}
Widget _buildChildren(BuildContext context, Widget child) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ClipRect(
child: Align(
heightFactor: _heightFactor.value,
child: child,
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
//執(zhí)行以下對應(yīng)的Tap事件
_handleTap();
final bool closed = !_isExpanded && _controller.isDismissed;
return AnimatedBuilder(
animation: _controller.view,
builder: _buildChildren,
child: closed ? null : Column(children: widget.children),
);
}
}
原理其實很簡單,就是根據(jù)字段_isExpanded 來控制折疊和展開瑟曲,內(nèi)部使用動畫實現(xiàn)對height的控制
Flutter 目前生態(tài)資源還是很缺乏饮戳,很多需要自定義,一般根據(jù)系統(tǒng)相關(guān)的控件做修改洞拨,是最好的