HarmonyOS 鸿蒙Next 置顶粘贴效果除了list的sticky还有别的方案吗?
HarmonyOS 鸿蒙Next 置顶粘贴效果除了list的sticky还有别的方案吗?
可以使用偏移量通过代码逻辑来实现,以下是简单的demo:
enum ScrollPosition {
start,
center,
end
}
class ItemClass {
content: string = '';
color: Color = Color.White;
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct NestedScroll {
[@State](/user/State) listPosition: number = ScrollPosition.start; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
[@State](/user/State) scrollPosition: number = ScrollPosition.start; // 0代表滚动到页面顶部,1代表中间值,2代表滚动到页面底部。
[@State](/user/State) showTitle: boolean = false;
[@State](/user/State) currentYOffset: number = 0;
private arr: ItemClass[] = [];
private colorArr: Color[] = [Color.White, Color.Blue, Color.Brown, Color.Green, Color.Gray];
private scrollerForScroll: Scroller = new Scroller();
private scrollerForList: Scroller = new Scroller();
private scrollerForTitle: Scroller = new Scroller();
[@State](/user/State) currentIndex: number = 0;
aboutToAppear() {
for(let i = 0; i < 6; i++) {
let data: ItemClass = {
content: i.toString(),
color: this.colorArr[i % 5]
}
this.arr.push(data);
}
}
[@Builder](/user/Builder) myBuilder() {
Row() {
List({ space: 2, initialIndex: 0, scroller: this.scrollerForTitle }) {
ForEach(this.arr, (item: ItemClass, index) => {
ListItem() {
Column() {
Text(item.content);
Divider()
.color('#000000')
.strokeWidth(5)
.visibility(index == this.currentIndex ? Visibility.Visible : Visibility.Hidden)
}
.width('25%')
.height(50)
.onClick(() => {
this.scrollerForList.scrollToIndex(index)
this.scrollerForScroll.scrollEdge(Edge.Bottom)
})
}
})
}
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
}
.backgroundColor('#ffe2d0d0')
.alignItems(VerticalAlign.Center)
}
build() {
Stack({ alignContent: Alignment.Top }) {
Scroll(this.scrollerForScroll) {
Column() {
Image($r('app.media.app_icon'))
.width("100%")
.height("40%")
this.myBuilder();
List({ space: 10, scroller: this.scrollerForList }) {
ForEach(this.arr, (item: ItemClass, index) => {
ListItem() {
Column() {
Text(item.content)
//添加其他内容
}
.width('100%')
.height(500)
.backgroundColor(item.color)
}.width("100%").height(500)
.onVisibleAreaChange([0.8], (isVisible) => {
if (isVisible) {
this.currentIndex = index;
this.scrollerForTitle.scrollToIndex(this.currentIndex);
}
})
}, (item: ItemClass) => item.content)
}
.padding({ left: 10, right: 10 })
.width("100%")
.edgeEffect(EdgeEffect.None)
.scrollBar(BarState.Off)
.onReachStart(() => {
this.listPosition = ScrollPosition.start
})
.onReachEnd(() => {
this.listPosition = ScrollPosition.end
})
.onScrollFrameBegin((offset: number, state: ScrollState) => {
// 滑动到列表中间时
if (!((this.listPosition == ScrollPosition.start && offset < 0)
|| (this.listPosition == ScrollPosition.end && offset > 0))) {
this.listPosition = ScrollPosition.center
}
// 如果页面已滚动到底部,列表不在顶部或列表有正向偏移量
if (this.scrollPosition == ScrollPosition.end
&& (this.listPosition != ScrollPosition.start || offset > 0)) {
return { offsetRemain: offset };
} else {
this.scrollerForScroll.scrollBy(0, offset)
return { offsetRemain: 0 };
}
})
.width("100%")
.height("calc(100% - 50vp)")
创建菜单时,如果普通的文本菜单不满足需求,可在bindMenu中传入CustomBuilder,创建自定义菜单。以下是简单的demo:
[@Entry](/user/Entry)
[@Component](/user/Component)
struct MenuExample {
[@State](/user/State) listData: number[] = [0, 0, 0]
[@Builder](/user/Builder) MenuBuilder() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
ForEach(this.listData, (item, index) => {
Column() {
Row() {
Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 })
Text(`Menu${index + 1}`).fontSize(20)
}
.width('100%')
.height(30)
.justifyContent(FlexAlign.Center)
.align(Alignment.Center)
.onClick(() => {
console.info(`Menu${index + 1} Clicked!`)
})
if (index != this.listData.length - 1) {
Divider().height(10).width('80%').color('#ccc')
}
}.padding(5).height(40)
})
}.width(100)
}
build() {
Column() {
Text('click for menu')
.fontSize(20)
.margin({ top: 20 })
.bindMenu(this.MenuBuilder)
}
.height('100%')
.width('100%')
.backgroundColor('#f0f0f0')
}
}
更多关于HarmonyOS 鸿蒙Next 置顶粘贴效果除了list的sticky还有别的方案吗?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙系统中,实现置顶粘贴效果除了使用List组件的sticky属性外,还存在其他方案。一种方法是利用自定义布局和动画效果来模拟置顶粘贴的行为。
具体来说,可以通过在数据更新时动态调整目标项的位置,同时利用动画效果使该项平滑地移动到置顶位置。这种方法需要精确地控制布局参数和动画插值器,以确保置顶效果的自然和流畅。
另外,还可以考虑使用ScrollView组件结合自定义的LayoutManager来实现置顶效果。通过重写LayoutManager的滚动逻辑,可以在滚动过程中检测到目标项的位置,并在需要时将其移动到置顶位置。这种方法需要对ScrollView和LayoutManager的工作原理有较深入的理解。
值得注意的是,无论采用哪种方案,都需要对UI性能进行优化,以避免因频繁布局或动画计算而导致的卡顿现象。
如果以上方案仍无法满足需求,或实现过程中遇到具体问题,建议直接参考HarmonyOS的官方文档或示例代码,以获取更详细的实现方法和最佳实践。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。