鸿蒙历史搜索功能:tag标签根据文字宽度自动换行 展示更多
一.需求
历史搜索功能,需要根据文字宽度自动换行,并且只展示3行,文字宽度不固定
二.思路
1.通过鸿蒙api MeasureText.measureText 先获取文字宽度
2.通过Row组件的onAreaChange事件监听当前组件高度变化
三.实现
监听需要展示的数量,是否返回完整的数据和需要截取的数量
定义需要用到的变量 如果是v1的话@Local换成@State即可
@Local isExpanded: boolean = false // 是否继续计算行高
@Local visibleItemCount: number = 0; // 当前可见的标签数量
@Local arr:string[] = ['123','123','123','123','123','123','123','123'];
//监听需要展示数量
@Computed
get displayList() {
return this.isExpanded
? this.arr
: this.arr.slice(0, this.visibleItemCount);
}
标签样式和布局样式
// 标签样式
@Builder
tagView(item: string) {
Column() {
Text(item)
.fontSize(14)
.fontWeight(400)
.fontColor('#666666')
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
}
.onClick(() => {
})
.height(32)
.borderRadius(6)
.backgroundColor('#F6F7F8')
.margin({ top: 8, right: 8 })
.padding({
left: 12,
right: 12,
top: 6,
bottom: 6
})
}
// 布局和监听高度判断
Column({ space: '8vp' }) {
Flex({
direction: FlexDirection.Row, // 横向排列
wrap: FlexWrap.Wrap, // 自动换行
justifyContent: FlexAlign.Start, // 左对齐
alignItems: ItemAlign.Center // 垂直居中对齐
}) {
ForEach(this.displayList), (item: string) => {
this.tagView(item); // ui样式抽成了Builder,换成自己的就行
}, (item: string, index: number) => JSON.stringify(item) + index);
// 展示更多按钮
if (this.isExpanded) {
this.moreButton();
}
}
.onAreaChange((oldValue: Area, newValue: Area) => {
if (this.isExpanded) {
return; // 已经点击“更多”按钮,直接返回,不再进行计算
}
const containerWidth = newValue.width; // 当前页面宽度用来存放标签的总宽度
// 最大高度 这里因为我每行高度是固定40,只展示3行所以是120,可以根据自己需求调整
const MAX_HEIGHT = 120;
if (newValue.height >= MAX_HEIGHT) {
this.showMoreButton = true; // 显示 "更多" 按钮
const visibleItemsCount = this.calculateVisibleItems2(Number(containerWidth), MAX_HEIGHT);
this.visibleItemCount = visibleItemsCount; // 更新当前可见标签数量
} else {
this.showMoreButton = false; // 隐藏 "更多" 按钮
this.visibleItemCount = this.arr.length; // 显示所有标签
}
});
}
高度和宽度计算
//计算显示几个标签 通过行高,最大行数,标签动态宽度
calculateVisibleItems2(containerWidth: number, maxHeight: number): number {
const LINE_HEIGHT = 40; // 每行固定高度
const MAX_LINES = Math.floor(maxHeight / LINE_HEIGHT); // 最大行数
let currentWidth = 0; // 当前行的宽度累加
let currentLine = 1; // 当前是第几行
let visibleCount = 0; // 可见的标签数量
for (let item of this.vm.searchHistoryList) {
const itemWidth = this.getTagWidth(item); // 获取标签宽度
if (currentWidth + itemWidth <= containerWidth) {
// 标签可以放入当前行
currentWidth += itemWidth;
} else {
// 换行
currentLine++;
if (currentLine > MAX_LINES) {
break; // 超过最大行数,停止计数
}
currentWidth = itemWidth; // 新行的第一个标签宽度
}
visibleCount++; // 增加可见的标签数量
}
return visibleCount;
}
展示更多按钮
@Builder
moreButton() {
Column() {
Text('展示更多')
}
.height(32)
.width(32)
.backgroundColor('#F6F7F8')
.borderRadius(6)
.margin({ top: 8, right: 8 })
.padding({
left: 12,
right: 12,
top: 6,
bottom: 6
})
.onClick(() => {
this.isExpanded = true; // 标记为已展开
this.visibleItemCount = this.arr.length; // 更新为显示所有标签
})
}