Flutter之ExpansionTile实现以代码方式码折叠、展开

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

猜你喜欢

转载自blog.csdn.net/adojayfan/article/details/129816845
今日推荐