HarmonyOS鸿蒙Next中Swiper实践分享:Swiper组件如何做同屏多个,每个宽度不一样的效果
HarmonyOS鸿蒙Next中Swiper实践分享:Swiper组件如何做同屏多个,每个宽度不一样的效果
如果想要实现同屏多个子页面,并且每个子页面宽度不一样的效果,可以考虑使用Swiper的自定义动画。在自定义动画中,可以自由控制每个子页面的scale和translate属性。
3 回复
可以参考以下demo:
// xxx.ets
@Entry
@Component
struct SwiperCustomAnimationExample {
private DISPLAY_COUNT: number = 2;
private MIN_SCALE: number = 0.75;
@State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange];
@State opacityList: number[] = [];
@State scaleList: number[] = [];
@State translateList: number[] = [];
@State zIndexList: number[] = [];
aboutToAppear(): void {
for (let i = 0; i < this.backgroundColors.length; i++) {
this.opacityList.push(1.0);
this.scaleList.push(1.0);
this.translateList.push(0.0);
this.zIndexList.push(0);
}
}
build() {
Column() {
Swiper() {
ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => {
Text(index.toString()).width('100%').height('100%').fontSize(50).textAlign(TextAlign.Center)
.backgroundColor(backgroundColor)
// 自定义动画变化透明度、缩放页面、抵消系统默认位移、渲染层级等
.opacity(this.opacityList[index])
.scale({ x: this.scaleList[index], y: this.scaleList[index] })
.translate({ x: this.translateList[index] })
.zIndex(this.zIndexList[index])
})
}
.height(300)
.indicator(false)
.displayCount(this.DISPLAY_COUNT, true)
.customContentTransition({
// 页面移除视窗时超时1000ms下渲染树
timeout: 1000,
// 对视窗内所有页面逐帧回调transition,在回调中修改opacity、scale、translate、zIndex等属性值,实现自定义动画
transition: (proxy: SwiperContentTransitionProxy) => {
if (proxy.position <= proxy.index % this.DISPLAY_COUNT || proxy.position >= this.DISPLAY_COUNT + proxy.index % this.DISPLAY_COUNT) {
// 同组页面往左滑或往右完全滑出视窗外时,重置属性值
this.opacityList[proxy.index] = 1.0;
this.scaleList[proxy.index] = 1.0;
this.translateList[proxy.index] = 0.0;
this.zIndexList[proxy.index] = 0;
} else {
// 同组页面往右滑且未滑出视窗外时,对同组中左右两个页面,逐帧根据position修改属性值,实现两个页面往Swiper中间靠拢并透明缩放的自定义切换动画
if (proxy.index % this.DISPLAY_COUNT === 0) {
this.opacityList[proxy.index] = 1 - proxy.position / this.DISPLAY_COUNT;
this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - proxy.position / this.DISPLAY_COUNT);
this.translateList[proxy.index] = -proxy.position * proxy.mainAxisLength + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0;
} else {
this.opacityList[proxy.index] = 1 - (proxy.position - 1) / this.DISPLAY_COUNT;
this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - (proxy.position - 1) / this.DISPLAY_COUNT);
this.translateList[proxy.index] = -(proxy.position - 1) * proxy.mainAxisLength - (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0;
}
this.zIndexList[proxy.index] = -1;
}
}
})
.onContentDidScroll((selectedIndex: number, index: number, position: number, mainAxisLength: number) => {
// 监听Swiper页面滑动事件,在该回调中可以实现自定义导航点切换动画等
console.info("onContentDidScroll selectedIndex: " + selectedIndex + ", index: " + index + ", position: " + position + ", mainAxisLength: " + mainAxisLength);
})
}.width('100%')
}
}
更多关于HarmonyOS鸿蒙Next中Swiper实践分享:Swiper组件如何做同屏多个,每个宽度不一样的效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中实现同屏多个宽度不同的Swiper组件,可使用Swiper的displayMode
属性设置为autoLinear
模式,并自定义每个Swiper子项的宽度。通过设置itemSize
为固定值或百分比来控制宽度差异。在布局文件中为每个Swiper子项单独设置宽度样式,或使用ForEach
动态绑定不同宽度值。示例代码片段:
Swiper({
displayMode: SwiperDisplayMode.AutoLinear,
itemSize: '50%' // 可根据需求设置为不同值
}) {
ForEach(this.items, (item, index) => {
Column() {
// 内容
}.width(this.getItemWidth(index)) // 动态宽度函数
})
}
在HarmonyOS Next中实现同屏多个不同宽度Swiper组件的效果,可以通过以下方案实现:
- 核心思路是利用Swiper的loop和customStyle属性配合自定义动画:
Swiper({
loop: true,
customStyle: true
}) {
// 子页面内容
}
- 为每个子项设置不同宽度:
ForEach(this.items, (item, index) => {
Column() {
// 内容
}
.width(`${item.width}%`) // 设置不同宽度
.height('100%')
}, (item) => item.id)
- 关键点:
- 使用customStyle:true启用自定义样式
- 通过transform控制位置和缩放
- 配合onChange事件动态调整样式
- 建议设置itemSpace留出间距
- 完整示例:
@State currentIndex: number = 0
build() {
Swiper({
loop: true,
customStyle: true,
onChange: (index: number) => {
this.currentIndex = index
}
}) {
ForEach(this.items, (item, index) => {
Column() {
// 内容
}
.width(`${item.width}%`)
.transform(this.getTransform(index))
})
}
}
private getTransform(index: number): object {
// 根据currentIndex计算每个item的transform值
// 可以实现错位、缩放等效果
}
注意要合理处理item间距和transform计算,确保滑动流畅性和视觉效果。