直接說具體需求樣式吧
一行裡有三個widget,只有第一個widget內容確定,第二個widget內容由介面返回,返回什麼顯示什麼,第三個widget,位置也由第二個確定。只顯示一排,如果內容過多,widget2要省略以...可見
結束。
畫個圖吧,清晰點,然後在給出一個具體樣子。
具體栗子: 這是一個提示語:widget1: 最大發布範圍 widget2:為介面返回釋出範圍名單,可能很長,也可能很短。當很長時,widget1、3都確定了位置,widget2儘可能的顯示多的內容,然後以"...可見"文案結束。 可能是下面這樣:
eg1:最大可見範圍:張三、李四、王五三人可見。 ✅ (widget2 內容很少時)
eg2:最大可見範圍:張三、李四、王五、趙...等26人可見。✅ (widget2 內容很多,超過了一行最大顯示時)
UED效果圖:
實現方式:
方式一:
Row-> widget1 -> Container(
BoxConstraints 限定寬度約束)->widget2/widget3
Row(children: [
Container(
constraints: BoxConstraints(
minWidth: margin,
maxWidth: MediaQuery.of(context).size.width - margin),
child: Text(
str,
style: titleStyle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Text(
endStr,
style: StyleConstant.subtitleStyle,
)
]);
複製程式碼
實現二:
使用系統的自帶的CustomMultiChildLayout
,自定義一個widget 繼承自它
class MultipleChildWrapWidget extends CustomMultiChildLayout {
MultipleChildWrapWidget({Key key, List<Widget> children})
: super(
key: key, children: children, delegate: MultiChildrenWidgetDelegate());
}
class MultiChildrenWidgetDelegate extends MultiChildLayoutDelegate {
@override
void performLayout(Size size) {
// 一行裡剩餘的size
var surplus = Size(size.width, size.height);
// 第一個控制元件
if (hasChild("former")) {
var formerSize = layoutChild("former", BoxConstraints.loose(surplus));
positionChild("former", Offset.zero);
//更新剩餘size
surplus = Size(surplus.width - formerSize.width, surplus.height);
}
// 第二個控制元件
if (hasChild("middle") && hasChild("last")) {
// 先計算最後一個控制元件
var lastSize = layoutChild("last", BoxConstraints.loose(surplus));
// 在計算中間控制元件
var middleSize = layoutChild("middle", BoxConstraints.loose(Size(surplus.width - lastSize.width, surplus.height)));
// 放置控制元件
positionChild("middle", Offset(size.width - surplus.width, 0));
positionChild("last", Offset(size.width - surplus.width + middleSize.width, 0));
}
}
複製程式碼
使用的時候只需將它作為一個widget即可,但要注意控制元件的id
不要寫錯了,前後要對應上。
使用例子:
Container(
child: MultipleChildWrapWidget(
children: [
LayoutId(id: "former", child: child), // 這個id 要和 裡面控制元件對應上
LayoutId(id: "middle", child: child,),
LayoutId(id: "last", child: child)
],
),
);
複製程式碼
同樣類似的需求
彈窗提示,最多展示兩行文字,超過兩行以"...可見"結束。
實現方式
最開始想用偷雞方式實現來著,讓文字就顯示兩行,然後第二行底部用"...可見"Text覆蓋上去。 很快三下五初二幹完了,搞定, 哈哈? 理想很豐滿,現實很果敢啊。 一執行發現,後面直接蓋一個固定的widget會有問題,可能壓住了半邊字,你懂的哈。
不行那就換一種吧。後來又想兩行分別顯示,第二行用兩個widget組合來顯示。 但是問題又來了,怎麼確定每行顯示多少文字呢?在哪個文字那裡斷開呢?? 這樣就得一個一個字的繪製出來,太麻煩,不想這麼幹。 程式猿都是懶人嘛,我要找簡便的方法。
既然文字超過固定的行數,會以"..."結束,那我能不能自定義讓其以"...可見"
結束呢?? 這不就實現了我的要求了麼!! 嗯,這樣很好。 於是就去看省略樣式設定overflow: TextOverflow.ellipsis
。 然而TextWidget
系統給出的省略樣式就那幾種,還不能自定義。
不行,我不幹,既然你這能給出那幾種省略樣式,就可以設定別的樣式。 我繼續找,你Text不行,我找其他的東西。那我自己畫的方式呢,TextPainter
;
TextPainter({
InlineSpan? text,
TextAlign textAlign = TextAlign.start,
TextDirection? textDirection,
double textScaleFactor = 1.0,
int? maxLines,
String? ellipsis,
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
})
複製程式碼
誒,這裡可以把ellipsis
傳進來,那我就用我自己希望的String當結尾就好了啊。
這個貌似可以。 嘿嘿 就是你了。
自定義一個widget繼承自CustomPainter
, 實現對應的協議即可。
class CustomTextPaintWidget extends CustomPainter {
final String text;
final String endStr;
final TextStyle textStyle;
final int maxLines;
TextPainter _textPainter;
CustomTextPaintWidget({this.text, this.endStr,this.textStyle, this.maxLines}) {
_textPainter = TextPainter(
text: TextSpan(text: text, style: textStyle),
maxLines: maxLines,
ellipsis: endStr,
textDirection: TextDirection.ltr);
}
@override
void paint(Canvas canvas, Size size) {
_textPainter.layout(maxWidth: size.width);
_textPainter.paint(canvas, Offset(0, 0));
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
複製程式碼
使用方式如下,就是一個widget
。
這個也可以解決上面那個問題。
Widget CustomPaint(
size: Size(MediaQuery.of(context).size.width - margin, 20),
painter: CustomTextPaintWidget(
text: str,
endStr: endStr,
textStyle: TextStyle,
maxLines: 2),
);
複製程式碼
完美 搞定。?
其實需求很簡單,不要急,先想好在幹,總會有更優的方式。
如果大佬有更好的實現樣式,還望不吝賜教,小弟在此先感謝了[抱拳].