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();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现 WebView 白屏检测可以通过监听 WebView 加载状态来进行判断。具体实现方法如下: 1. 在初始化 WebView 的时候,设置一个加载状态的标识位: ```dart bool _isLoading = true; WebView( initialUrl: _url, onPageStarted: (String url) { setState(() { _isLoading = true; }); }, onPageFinished: (String url) { setState(() { _isLoading = false; }); }, ) ``` 2. 在页面加载完成后,判断 WebView 是否出现白屏: ```dart bool _isBlankPage(WebView webview) { return _isLoading && webview.controller?.currentUrl == null; } ``` 3. 如果出现白屏,可以进行一些处理,比如重新加载页面或者提示用户网络不稳定等。 完整代码示例: ```dart import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebViewPage extends StatefulWidget { final String url; const WebViewPage({Key key, this.url}) : super(key: key); @override _WebViewPageState createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { bool _isLoading = true; WebViewController _controller; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.url), ), body: WebView( initialUrl: widget.url, onPageStarted: (String url) { setState(() { _isLoading = true; }); }, onPageFinished: (String url) { setState(() { _isLoading = false; }); }, onWebViewCreated: (WebViewController controller) { _controller = controller; }, ), ); } bool _isBlankPage(WebViewController controller) { return _isLoading && controller?.currentUrl == null; } void _reload() { _controller?.reload(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值