HarmonyOS Swiper组件两边子组件不能设置高度

使用Swiper组件进行卡片列表的使用,卡片等级在滑动切换时,中间的子组件显示是正常高度,两边的子组件需要将高度设置小一些,并且居中显示。

阻塞点:在Swiper组件里,两边子组件不能设置高度。

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
shlp

可参考如下demo使用缩放实现:

@Entry
@Component
struct SwiperDemo {
  private swiperController: SwiperController = new SwiperController();
  @State currentIndex: number = 0;
  @State TargetIndex: number = 0;
  @State currentOffset: number = 0;
  @State isCurrent: Boolean = false;
  @State isFirst: number = 1;
  @State isSecond: number = 0.5;
  @State isThird: number = 0.5;

  build() {
    Column() {
      Swiper(this.swiperController) {
        Image($r('app.media.background')).width(250).height(250).scale({ x: this.isFirst, y: this.isFirst })
        Image($r('app.media.foreground')).width(250).height(250).scale({ x: this.isSecond, y: this.isSecond })
        Image($r('app.media.startIcon')).width(250).height(250).scale({ x: this.isThird, y: this.isThird })
      }
      .indicator(true)
      .itemSpace(30)
      .duration(600)
      .onGestureSwipe((index: number,
        extraInfo: SwiperAnimationEvent) => {
        // 左滑动效
        if (index === 0 && extraInfo.currentOffset < 0) {
          this.isFirst = 1 + extraInfo.currentOffset / 500;
          this.isSecond = 0.5 - 1 / 250 * extraInfo.currentOffset;
        }
        if (index === 1 && extraInfo.currentOffset < 0) {
          this.isSecond = 1 + extraInfo.currentOffset / 500;
          this.isThird = 0.5 - 1 / 250 * extraInfo.currentOffset;
        }
        if (index === 2 && extraInfo.currentOffset < 0) {
          this.isThird = 1 + extraInfo.currentOffset / 500;
          this.isFirst = 0.5 - 1 / 250 * extraInfo.currentOffset;
        }
        // 右滑动效
        if (index === 0 && extraInfo.currentOffset > 0) {
          this.isFirst = 1 - extraInfo.currentOffset / 500;
          this.isThird = 0.5 + 1 / 250 * extraInfo.currentOffset;
        }
        if (index === 1 && extraInfo.currentOffset > 0) {
          this.isSecond = 1 - extraInfo.currentOffset / 500;
          this.isFirst = 0.5 + 1 / 250 * extraInfo.currentOffset;
        }
        if (index === 2 && extraInfo.currentOffset > 0) {
          this.isThird = 1 - extraInfo.currentOffset / 500;
          this.isSecond = 0.5 + 1 / 250 * extraInfo.currentOffset;
        }
      })
      .onAnimationEnd((index: number) => {
        animateTo({
          duration: 500,
          curve: Curve.EaseOut,
          iterations: 1,
          playMode: PlayMode.Normal,
          onFinish: () => {
            console.info('play end')
          }
        }, () => {
          if (index == 0) {
            this.isFirst = 1;
            this.isSecond = 0.5;
            this.isThird = 0.5;
          } else if (index == 1) {
            this.isFirst = 0.5;
            this.isSecond = 1;
            this.isThird = 0.5;
          } else if (index == 2) {
            this.isFirst = 0.5;
            this.isSecond = 0.5;
            this.isThird = 1;
          }
        })
      })
    }.width('100%').border({ width: 1 }).backgroundColor(Color.Pink).margin({ top: 5 })
  }
}
// xxx.ets
import constant from '@ohos.bluetooth.constant'

class MyDataSource implements IDataSource {
  private list: string[] = []

  constructor(list: string[]) {
    this.list = list
  }

  totalCount(): number {
    return this.list.length
  }

  getData(index: number): string {
    return this.list[index]
  }

  registerDataChangeListener(listener: DataChangeListener): void {
  }

  unregisterDataChangeListener() {
  }
}

const MAX_SCALE = 1 // 最大缩放
const MIN_SCALE = 0.8 // 最小缩放
// 可通过以下两个参数变化观察效果,然后优化
const PAGE_DURATION = 100 // 子控件动画时长
const SWIPER_DURATION = 500 // swiper组件切换动画时长
// 拖动时用来计算缩放,影响拖动缩放速度,可根据屏幕尺寸来定
const DRAGGING_MAX_DISTANCE = 1000

@Entry
@Component
struct Gauge3 {
  private swiperController: SwiperController = new SwiperController()
  private data: MyDataSource = new MyDataSource([])
  @State currentIndex: number = 0
  @State scaleArray: number[] = [];
  startSwiperOffset: number = 0

  aboutToAppear(): void {
    let list: string[] = []
    for (let i = 0; i <= 5; i++) {
      list.push(i.toString());
      this.scaleArray.push(i == 0 ? MAX_SCALE : MIN_SCALE)
    }
    this.data = new MyDataSource(list)
  }

  build() {
    Column({ space: 25 }) {
      Swiper(this.swiperController) {
        LazyForEach(this.data, (item: string, index: number) => {
          Column() {
            Text(item)
              .width(40)
              .height(40)
              .textAlign(TextAlign.Center)
              .fontSize(30)
          }
          .width("100%")
          .height('100%')
          .backgroundColor(0xFFFF00)
          .scale({ x: this.scaleArray[index], y: this.scaleArray[index] })
          .animation({
            duration: PAGE_DURATION,
            curve: Curve.Linear
          })
        }, (item: string, index: number) => item)
      }
      .displayMode(SwiperDisplayMode.STRETCH)
      .displayCount(1)
      .width('100%')
      .height('100%')
      .index(this.currentIndex) //状态变量
      .cachedCount(2)
      .indicator(true)
      .duration(SWIPER_DURATION)
      .itemSpace(0)
      .nextMargin(40)
      .prevMargin(40)
      .curve(Curve.Linear)
      .backgroundColor(0x999999)
      .onChange((index: number) => {
        this.currentIndex = index
        this.scaleArray[this.currentIndex] = MAX_SCALE;
        if (this.currentIndex == 0) {
          this.scaleArray[this.scaleArray.length - 1] = MIN_SCALE
        } else {
          this.scaleArray[this.currentIndex -1] = MIN_SCALE
        }
        if (this.currentIndex == this.scaleArray.length - 1) {
          this.scaleArray[0] = MIN_SCALE
        } else {
          this.scaleArray[this.currentIndex + 1] = MIN_SCALE
        }
      })
      .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => {
        if (this.startSwiperOffset == 0) {
          this.startSwiperOffset = extraInfo.currentOffset;
        }
        let offset: number = extraInfo.currentOffset
        let currentScale: number = this.scaleArray[index]
        let nextIndex = (index == this.scaleArray.length - 1 ? 0 : index + 1)
        let preIndex = (index == 0 ? this.scaleArray.length - 1 : index - 1)
        let nextScale: number = this.scaleArray[nextIndex]
        let preScale: number = this.scaleArray[preIndex]

        // 滑动距离
        let distance = Math.abs(this.startSwiperOffset - offset)
        currentScale = MAX_SCALE - Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE)
        if (this.startSwiperOffset > offset) {
          nextScale = MIN_SCALE + Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE)
          preScale = MIN_SCALE
        } else {
          preScale = MIN_SCALE + Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE)
          nextScale = MIN_SCALE
        }
        this.scaleArray[this.currentIndex] = currentScale
        this.scaleArray[nextIndex] = nextScale
        this.scaleArray[preIndex] = preScale
      })
      .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
        if (index == targetIndex) {
          let nextIndex = (index == this.scaleArray.length - 1 ? 0 : index + 1)
          let preIndex = (index == 0 ? this.scaleArray.length - 1 : index - 1)
          this.scaleArray[index] = MAX_SCALE
          this.scaleArray[nextIndex] = MIN_SCALE
          this.scaleArray[preIndex] = MIN_SCALE
        } else {
          let nextIndex = (targetIndex == this.scaleArray.length - 1 ? 0 : targetIndex + 1)
          let preIndex = (targetIndex == 0 ? this.scaleArray.length - 1 : targetIndex - 1)
          this.scaleArray[targetIndex] = MAX_SCALE
          this.scaleArray[nextIndex] = MIN_SCALE
          this.scaleArray[preIndex] = MIN_SCALE
        }
      })
      .onAnimationEnd((index: number, extraInfo: SwiperAnimationEvent) => {
        this.startSwiperOffset = 0
      })
    }
    .width('100%')
    .height('20%')
    .margin({ top: 5 })
  }
}
分享
微博
QQ
微信
回复
2天前
相关问题
半模态弹窗如何禁止两边触摸
164浏览 • 0回复 待解决
API8怎么设置顶部两边圆角底部直角
2192浏览 • 1回复 待解决
Swiper组件如何设置导航点位置
2456浏览 • 1回复 待解决
设置组件的宽度不超出父组件
661浏览 • 1回复 待解决
Swiper组件设置不跟随手势滑动
655浏览 • 1回复 待解决