hello,大家好,今天为大家介绍一个小控件,就是以图片开始的Text;如果你的文字需要多行显示,并且在开头的位置要能添加图片。不妨试试这个控件,图片会自适应文字的高度来显示;
安卓原生的TextView就自带drawableLeft等,使用很简单,到Flutter就得自己想办法了,这个控件以前帮别人写的,现在贡献出来,大家再也不用去为这些小控件去发愁,去查找了;老规矩,还是先看图,看一看图就知道是不是自己想要的了
这是仿天猫淘宝商品简述示例,还是先照顾快速开发的小伙伴,先看看怎么去使用控件呢
第一步:添加以下代码到你的 pubspec.yaml 文件
dependencies:
drawablestarttext: ^0.1.1
第二步:导包,复制下面代码到你要使用的文件下
import 'package:drawablestarttext/drawablestarttext.dart';
第三步:写你的业务代码(以下为我写的示例代码)
import 'package:flutter/material.dart';
import 'package:drawablestarttext/drawablestarttext.dart';
class DrawableStartTextDemo extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("DrawableStartText"),
),
body: new Center(
child: new Container(
child: new DrawableStartText(
assetImage: "images/tianmao.jpg",
text: " 莫顿 全自动感应壁挂式酒精喷雾式手消毒器 手消毒机杀菌净手器",
textStyle: new TextStyle(fontSize: 17.0),
),
),
),
);
}
}
大家只需要设置要显示的文字,文字的样式,和要显示的图片即可,这样demo已经可以跑起来了,还有一个变量maxLines,用来设置显示多少行,使用很简单,就不再赘述了,下面我们看看怎么实现的
我是将文字分开显示的 也就是说在2个Text显示的,那怎么去截取2段文字呢,这就要取决于图片的宽度了,但是图片的长宽比例不一样,缩放后宽度也不一样,所以我们第一步要做的就是缩放图片,并计算图片宽度
@override
void initState() {
super.initState();
//计算文字的高度,根据文字的高度设定图片的高度,然后让图片自适应
TextPainter painter=new TextPainter();
if(widget.textStyle!=null) {
painter.text = TextSpan(style: widget.textStyle, text: widget.text);
}else{
painter.text = TextSpan(text: widget.text);
}
painter.maxLines=1;
painter.textDirection=TextDirection.ltr;
painter.layout();
_textHeight=painter.size.height;
}
↑↑↑上面的代码是计算文字的高度,文字有多高,我们将图片就设置多高
↓↓↓将文字的高度设置成图片的高度,还要设置下fit 参数,让他适应高度 BoxFit.fitHeight, 它会让图片等比例缩放来适应高度,下来我们看下build方法怎么设置图片的,顺便看下2个Text控件的摆放
@override
Widget build(BuildContext context) {
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Row(
key: rowKey,
children: [
_image=new Image.asset(
widget.assetImage,
key:imageKey,
height:_textHeight,
fit : BoxFit.fitHeight,
),
new Text(
_topText,
style: widget.textStyle,
maxLines: 1,
),
],
),
new Text(
_bottomText,
style: widget.textStyle,
textAlign: TextAlign.left,
maxLines: widget.maxLines ==null ? defaultTextStyle.maxLines : widget.maxLines-1,
overflow: widget.maxLines ==null ? defaultTextStyle.overflow : TextOverflow.ellipsis,
),
],
);
}
在第一次build之后,我们就可以拿到Image控件的宽高了,还有父控件Row的宽高,这样我们就能算出来第一行能显示多少个文字(第一行文字就是图片屁股后面的文字),然后截取文字,分段显示;
在写的时候,我发现在第一次build之后用key去获取Imge控件的宽高根本就不靠谱,经常返回null,报空指针异常,我呢,就根据缩放比例算出的宽高,再依次算出第一行剩下可显示文字的宽度(先假设叫 FirstRowTextWidth)
那怎么判断文字刚好够显示呢,我开了一个循环,每次累加一个字母,测量字母宽度是不是超过了FirstRowTextWidth,没超过就继续累加,直到超过为止 ,跳出循环;这时候我们就知道多少了字母不会超过了,(超过的哪个字母的前一个字母肯定没有超过FirstRowTextWidth),好了,看代码
//在第一帧后计算下第一行能显示多少个字母,然后将字母分成两段显示
WidgetsBinding.instance.addPostFrameCallback((callback){
_image.image.resolve(new ImageConfiguration())
.addListener((imageInfo,synchronousCall){
//计算图片的宽高
double imgHeight = imageInfo.image.height . toDouble();
double imgWidth = imageInfo.image.width . toDouble();
//由于图片缩放了。所以根据缩放大小计算出宽图,这里没有用key去取值,是因为取出的值是空的
double scale=_textHeight/imgHeight;
double _imageWidth=imgWidth*scale;
//再用父控件的宽度减去图片的宽度就是文字显示的宽度
double parentWidth = rowKey.currentContext.findRenderObject().paintBounds.size.width;
double textWidth = parentWidth - _imageWidth;
int index=0;
//计算出在哪个字母时超出了显示范围
for(;indextextWidth){
break;
}
}
//将超出的哪个位置减掉,剩下的字母就不会超出范围了
int validIndex=index-1;
//根据计算的位置,分别截取前半部分 和后半部分显示
setState(() {
_topText= widget.text.substring(0,validIndex);
_bottomText = widget.text.substring(validIndex);
});
});
});
}
代码就这么多,是不是很简单,快去尝试一下吧。如果在使用的过程中有什么问题,也请留言,随时为你解答,
最后附上源码地址:https://github.com/OpenFlutter/PullToRefresh
里面有很多更酷的控件,欢迎Star;如果喜欢Flutter,可以加入我们哦,我们的QQ群是 :892398530