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();