Flutter自带的ExpansionTile
只能通过点击标题触发展开和折叠,有时候我们想要以代码的方式控制,那满足不了我们的需求。我们只能修改源码。
复制源码
复制ExpansionTile
的源码到一个新的dart文件中,比如CustomExpansionTile
。修改类名
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
const Duration _kExpand = Duration(milliseconds: 200);
/// A single-line [ListTile] with an expansion arrow icon that expands or collapses
/// the tile to reveal or hide the [children].
///
/// This widget is typically used with [ListView] to create an
/// "expand / collapse" list entry. When used with scrolling widgets like
/// [ListView], a unique [PageStorageKey] must be specified to enable the
/// [ExpansionTile] to save and restore its expanded state when it is scrolled
/// in and out of view.
///
/// This class overrides the [ListTileThemeData.iconColor] and [ListTileThemeData.textColor]
/// theme properties for its [ListTile]. These colors animate between values when
/// the tile is expanded and collapsed: between [iconColor], [collapsedIconColor] and
/// between [textColor] and [collapsedTextColor].
///
/// The expansion arrow icon is shown on the right by default in left-to-right languages
/// (i.e. the trailing edge). This can be changed using [controlAffinity]. This maps
/// to the [leading] and [trailing] properties of [ExpansionTile].
///
/// {@tool dartpad}
/// This example demonstrates different configurations of ExpansionTile.
///
/// ** See code in examples/api/lib/material/expansion_tile/expansion_tile.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [ListTile], useful for creating expansion tile [children] when the
/// expansion tile represents a sublist.
/// * The "Expand and collapse" section of
/// <https://material.io/components/lists#types>
class CustomExpansionTile extends StatefulWidget {
/// Creates a single-line [ListTile] with an expansion arrow icon that expands or collapses
/// the tile to reveal or hide the [children]. The [initiallyExpanded] property must
/// be non-null.
const CustomExpansionTile(...);
/// 代码太长省略....
}
class ExpansionTileState extends State<CustomExpansionTile> with SingleTickerProviderStateMixin {
/// 代码太长省略....
}
因为使用的时候需要使用context来获取到State,必须去掉下划线.
/// _ExpansionTileState改为ExpansionTileState
class ExpansionTileState extends State<CustomExpansionTile> with SingleTickerProviderStateMixin{
.....
}
增加2个方法用来展开、折叠
在State中,有一个变量_isExpanded
,保存的是当前状态。
有一个方法_handleTap()
,是处理点击事情的,折叠时点击会自动展开,展开时点击会自动折叠了。
所以我们只需要在适当的时候调用_handleTap()
即可。
void _handleTap() {
setState(() {
_isExpanded = !_isExpanded;
if (_isExpanded) {
_controller.forward();
} else {
_controller.reverse().then<void>((void value) {
if (!mounted)
return;
setState(() {
// Rebuild without widget.children.
});
});
}
PageStorage.of(context)?.writeState(context, _isExpanded);
});
widget.onExpansionChanged?.call(_isExpanded);
}
添加2个方法
/// 折叠
void collapse(){
if(_isExpanded){
/// 只有在展开状态下才会触发
_handleTap();
}
}
/// 展开
void expand(){
if(!_isExpanded){
/// 只有在折叠状态下才会触发
_handleTap();
}
}
使用
首先,创建一个GlobalKey
.
/// 记得加上泛型
GlobalKey<ExpansionTileState> expansionKey = GlobalKey();
将key传递给我们自定义的CustomExpansionTile
ExpansionTile(key: expansionKey,title: Text('我是标题'),children: [
Container(
height: 300,
child: Center(
child: Text('这是展开的内容'),
),
),
],),
需要展开或者折叠的时候使用key获取到state后调用方法
/// 展开
expansionKey.currentState!.expand();
/// 折叠
expansionKey.currentState!.collapse();