hello,大家好,今天爲大家介紹一個小控件,就是以圖片開始的Text;如果你的文字需要多行顯示,並且在開頭的位置要能添加圖片。不妨試試這個控件,圖片會自適應文字的高度來顯示;
安卓原生的TextView就自帶drawableLeft等,使用很簡單,到Flutter就得自己想辦法了,這個控件以前幫別人寫的,現在貢獻出來,大家再也不用去爲這些小控件去發愁,去查找了;老規矩,還是先看圖,看一看圖就知道是不是自己想要的了
這是仿天貓淘寶商品簡述示例,還是先照顧快速開發的小夥伴,先看看怎麼去使用控件呢
Usage
第一步:添加以下代碼到你的 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: <Widget>[
new Row(
key: rowKey,
children: <Widget>[
_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(;index<widget.text.length;index++){
if(widget.textStyle!=null) {
painter.text = TextSpan(style: widget.textStyle, text: widget.text.substring(0,index));
}else{
painter.text = TextSpan(text: widget.text.substring(0,index));
}
painter.layout();
if(painter.size.width>textWidth){
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