Flutter's ExpansionTile implements code folding and expansion

The built-in Flutter ExpansionTilecan only trigger expansion and collapse by clicking on the title. Sometimes we want to control it by code, which cannot meet our needs. We can only modify the source code.

copy source code

Copy ExpansionTilethe source code into a new dart file, eg CustomExpansionTile. Modify class name

// 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 {
    
    
	/// 代码太长省略....
}

Because you need to use the context to get the State when using it, you must remove the underscore.

/// _ExpansionTileState改为ExpansionTileState
class ExpansionTileState extends State<CustomExpansionTile> with SingleTickerProviderStateMixin{
    
    
	.....
}

Add 2 methods to expand and fold

In State, there is a variable _isExpandedthat saves the current state.
There is a method _handleTap()that handles clicks. When it is folded, it will automatically expand when it is clicked, and when it is expanded, it will automatically collapse when it is clicked.
So we just need to call it when appropriate _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);
  }

Add 2 methods

/// 折叠
void collapse(){
    
    
  if(_isExpanded){
    
    
  	/// 只有在展开状态下才会触发
    _handleTap();
  }
}
/// 展开
void expand(){
    
    
  if(!_isExpanded){
    
    
  	/// 只有在折叠状态下才会触发
    _handleTap();
  }
}

use

First, create a GlobalKey.

/// 记得加上泛型
GlobalKey<ExpansionTileState> expansionKey = GlobalKey();

Pass the key to our customCustomExpansionTile

ExpansionTile(key: expansionKey,title: Text('我是标题'),children: [
  Container(
    height: 300,
    child: Center(
      child: Text('这是展开的内容'),
    ),
  ),
],),

When you need to expand or collapse, use the key to get the state and call the method

/// 展开
expansionKey.currentState!.expand();
/// 折叠
expansionKey.currentState!.collapse();

Guess you like

Origin blog.csdn.net/adojayfan/article/details/129816845