前提:
自学Flutter的第二周,已经可以自定义一些自己想要的控件了(仅限于简单点的),比如网络加载时的状态显示(loading,error,empty等),还有就是封装了loading 和第三方刷新加载库 SmartRefresher,在做网络加载时仅用一个自定义widget就可以做以上所有操作,不需要自己处理刷新和加载更多还有展示loading,error等操作,改天有时间发布一下。
回归正题,因为自己做项目的过程中,需要用到可伸缩的Text,在网上找寻第三方库的时候没有找到适合自己的,有些是因为显示问题,有些是因为滑动冲突,所以决定自己写一个。
收缩效果:
展开效果:
思路如下:
第一,因为要显示伸缩的文字,说到底还是文字,所以自定义的widget里面需要有Text。
第二,需求是text缩起来时显示几行,然后扩展开时,显示全部文字,
第三,需要一个icon之类的按钮在文字下面,缩起来显示向下图标,展开全部时显示向上图标
第四,就是StatelessWidget(无状态)和StatefulWidget(有状态)的选择, 因为我们这里需要变换图标还有行数,所以就选后面的StatefulWidget。
具体思路就写在源码里面的注释了,如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ExpandText extends StatefulWidget {
final String text; // 要显示的文字
final int shrinkLines;// 收缩时要显示多少行 默认值为2
final IconData shrinkIcon; // 收缩时候显示的icon 默认为Icons.keyboard_arrow_down
final IconData expandIcon; // 展开时候显示的icon 默认为Icons.keyboard_arrow_down
ExpandText(
{@required this.text,// 必传参数
this.shrinkLines = 2,
this.shrinkIcon = Icons.keyboard_arrow_down,
this.expandIcon = Icons.keyboard_arrow_up});
@override
createState() => _ExpandTextState();
}
class _ExpandTextState extends State<ExpandText> {
bool _isShrinkState = true; // 是否是缩小状态
@override
Widget build(BuildContext context) {
// DefaultTextStyle 具体下面详细说明
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
//这里使用脚手架的原因是material下的Text不会有默认的下边黄色下划线,可以根据需求直接return 下面的Column
return Scaffold(
// 列布局 上面显示文字 下面显示icon按钮
body: Column(
children: [
Text(
widget.text,// 要显示的文字
// 三目运算 是否是收缩状态 是的话就显示传入或者默认为2的行数 不是的话就显示能显示的最大行数
maxLines: _isShrinkState ? widget.shrinkLines : defaultTextStyle.maxLines,
),
// 这里因为icon需要点击 但icon本身没有点击事件 就在外面包裹 GestureDetector手势 ,然后在onTap里实现点击事件
GestureDetector(
// 三目运算 是否是收缩状态 是的话就显示收缩时需要显示的icon(有默认图标) 不是的话就显示展开时需要显示的icon(也有默认值)
child: Icon(_isShrinkState ? widget.shrinkIcon : widget.expandIcon),
// 点击事件
onTap: () {
// 点击时设置状态当前 重新绘制,
setState(() {
if (_isShrinkState) {
_isShrinkState = false;
} else {
_isShrinkState = true;
}
});
},
),
],
),
);
}
}
直接复制就可以用,如果想要其他的比如颜色或者字体大小什么的,可以自己在参数里面加TextStyle,需要什么自己添加就行。
写这个控件的时候碰到了一个小难点(其实也不算难点),就是收缩的时候可以设置行数,展开的时候设置几行呢?总不能去根据字数和字体大小来计算出行数吧。然后我就想到了Text本身就是可以计算出要显示的行数的,我就点Text源码去看,找到maxLines这个参数,然后全局搜索,果然一段源码引起了我的注意
maxLines: maxLines ?? defaultTextStyle.maxLines,
这个??符号有点类似于三目运算,意思是第二个maxLines为空吗 不为空第一个maxLines就为第二个maxLines,否则的话就为defaultTextStyle.maxLines,就是能显示多少行就显示多少行。我点击一下defaultTextStyle,然后源码转到build方法第一行,
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
这时候我就把这一行代码复制到我自定义Text的build方法里面,使用了defaultTextStyle.maxLines这个最大值。
总结:Flutter和原生一样,并不是所有控件和效果都能在自带的widget里面找到,有时候可以去试着找第三方库或者自己定义一下,碰到难点就试着去读一下源码。到目前为止Flutter的学习资料还有第三方支持远远不如原生开发多,所以之后我如果碰到了一些问题或者思路都会在这里记录一下,帮助需要帮助的人,因为我也经常碰见难点需要帮助。当办法多了以后,问题就不是问题了。