【HarmonyOS】层级轮播卡片效果

【HarmonyOS】层级轮播卡片效果

一、功能效果:

1.上下堆叠由大到小的卡片层叠效果。

2.上层卡片可手势左右滑动,自动左滑动。

3.三层卡片随滑动,内容进行依次切换。

二、开发思路

【完整代码见章节三】

1.最上层使用swiper进行轮播效果的实现。

dart 复制代码
  @Builder
  HeadSwiperLayerView() {
    Swiper(this.swiperController) {
      this.HeadCard()
      this.MiddenCard()
      this.EndCard()
    }
    .loop(true)
    .autoPlay(true)
    .indicator(false)
    .duration(500)
    .curve(Curve.Friction)
    .displayMode(SwiperDisplayMode.STRETCH)
    .onChange(this.monChangeCallBack)
    .onAnimationEnd(this.monAnimationEndCallBack)

  }

  @Builder
  HeadCard() {
    Row() {
       if (this.HEAD_INDEX == this.mIndex) {
        Image(this.mImageResource[this.HEAD_INDEX])
          .BGCardCardWidthAndHeight()
          .opacity(this.mCardOpacity)
          .CardAnim()
          .borderWidth(px2vp(2))
          .borderColor(Color.Red)
          .backgroundColor(Color.Blue)

      }
    }
    .BGWidthAndHeight()
  }

// MiddenCard EndCard 卡片依照HeadCard进行创建

2.下层两个卡片使用stack堆叠,依次显示。

dart 复制代码
  build() {
    Stack({ alignContent: Alignment.Center }) {
      // 最底层卡片
      this.EndLayerView()

      // 中间层卡片
      this.MiddenLayerView()

      // 最上层swiper滑动层
      this.HeadSwiperLayerView()
    }
  }

3.整体卡片内容通过list数据进行链式切换。

dart 复制代码
  // 卡片图片资源池
  @State mImageResource: Array<string | Resource > = [
    $r("app.media.icon_img1"),
    $r("app.media.icon_img2"),
    $r("app.media.icon_img3"),
    $r("app.media.icon_img4"),
    $r("app.media.icon_img5"),
  ];
  

4.调整切换的index下标数据,控制数据切换,和逻辑计算。

dart 复制代码
  getImageResource(current: number, mIndex: number) {
    let currentPage: string | Resource = ''
    if (current == this.END_INDEX) {
      if (mIndex == this.HEAD_INDEX) {
        currentPage = this.mImageResource[2];
      } else if (mIndex == this.MIDDEN_INDEX) {
        currentPage = this.mImageResource[0];
      } else if (mIndex == this.END_INDEX) {
        currentPage = this.mImageResource[1];
      }
    } else if (current == this.MIDDEN_INDEX) {
      if (mIndex >= 2) {
        currentPage = this.mImageResource[0];
      } else {
        currentPage = this.mImageResource[mIndex+1];
      }
    } else if (current == this.HEAD_INDEX) {
      currentPage = this.mImageResource[this.mIndex];
    }

    return currentPage;
  }

5.细磨效果,添加透明度动画润色过渡操作的效果。(为了效果更好后续也可添加移动,放大缩小等。示例代码只是添加了透明度。)

三、DEMO示例代码:

滑动组件View

SlidingCardView.ets

dart 复制代码
/**
 * 层叠轮播图
 */
@Component
export default struct SlidingCardView {
  // 滑动层 透明背景宽高
  private BG_WIDTH: number = px2vp(800);
  private BG_HEIGHT: number = px2vp(800);
  // 滑动层 可视卡片宽高
  private BG_CARD_WIDTH: number = px2vp(700);
  private BG_CARD_HEIGHT: number = px2vp(800);
  private CARD_ANIM_START: number = 0.1;
  private CARD_ANIM_END: number = 1;
  private LAYER_CARD_ANIM_START: number = 0.9;
  private LAYER_CARD_ANIM_END: number = 1;
  // 移动下标
  @State mIndex: number = 0;

  @State mCardOpacity: number = this.CARD_ANIM_END;
  @State mLayerOpacity: number = this.LAYER_CARD_ANIM_END;
  // 卡片图片资源池
  @State mImageResource: Array<string | Resource > = [
    $r("app.media.icon_img1"),
    $r("app.media.icon_img2"),
    $r("app.media.icon_img3"),
    $r("app.media.icon_img4"),
    $r("app.media.icon_img5"),
  ];
  private swiperController: SwiperController = new SwiperController();
  private END_INDEX: number = 2;
  private MIDDEN_INDEX: number = 1;
  private HEAD_INDEX: number = 0;

  getImageResource(current: number, mIndex: number) {
    let currentPage: string | Resource = ''
    if (current == this.END_INDEX) {
      if (mIndex == this.HEAD_INDEX) {
        currentPage = this.mImageResource[2];
      } else if (mIndex == this.MIDDEN_INDEX) {
        currentPage = this.mImageResource[0];
      } else if (mIndex == this.END_INDEX) {
        currentPage = this.mImageResource[1];
      }
    } else if (current == this.MIDDEN_INDEX) {
      if (mIndex >= 2) {
        currentPage = this.mImageResource[0];
      } else {
        currentPage = this.mImageResource[mIndex+1];
      }
    } else if (current == this.HEAD_INDEX) {
      currentPage = this.mImageResource[this.mIndex];
    }

    return currentPage;
  }

  private monAnimationEndCallBack = (): void => {
    this.mLayerOpacity = 0.9;
  }

  private monChangeCallBack = (index: number): void => {
    this.mIndex = index;
    this.mCardOpacity = this.CARD_ANIM_START;
    this.mLayerOpacity = this.LAYER_CARD_ANIM_START;
    setTimeout(() => {
      this.mCardOpacity = this.CARD_ANIM_END;
      this.mLayerOpacity = this.LAYER_CARD_ANIM_END;
    }, 100);
  }

  @Builder
  EndLayerView() {
    Row() {
      Blank()
      Image(this.getImageResource(this.END_INDEX, this.mIndex))
        .width(px2vp(500))
        .height(px2vp(600))
        .opacity(this.mLayerOpacity)
        .CardAnim()
        .borderWidth(px2vp(2))
        .borderColor(Color.Red)
        .backgroundColor(Color.Black)
    }
    .width(px2vp(1000))
    .height(px2vp(800))
  }

  @Builder
  MiddenLayerView() {
    Row() {
      Blank()
      Image(this.getImageResource(this.MIDDEN_INDEX, this.mIndex))
        .width(px2vp(400))
        .height(px2vp(700))
        .opacity(this.mLayerOpacity)
        .CardAnim()
        .borderWidth(px2vp(2))
        .borderColor(Color.Red)
        .backgroundColor(Color.Red)
    }
    .width(px2vp(800))
    .height(px2vp(800))
  }

  @Builder
  HeadCard() {
    Row() {
       if (this.HEAD_INDEX == this.mIndex) {
        Image(this.mImageResource[this.HEAD_INDEX])
          .BGCardCardWidthAndHeight()
          .opacity(this.mCardOpacity)
          .CardAnim()
          .borderWidth(px2vp(2))
          .borderColor(Color.Red)
          .backgroundColor(Color.Blue)

      }
    }
    .BGWidthAndHeight()
  }

  @Builder
  MiddenCard() {
    Row() {
      if (this.MIDDEN_INDEX == this.mIndex) {
        Image(this.mImageResource[this.MIDDEN_INDEX])
          .BGCardCardWidthAndHeight()
          .opacity(this.mCardOpacity)
          .CardAnim()
          .borderWidth(px2vp(2))
          .borderColor(Color.Red)
          .backgroundColor(Color.Blue)

       }
    }
    .BGWidthAndHeight()
  }

  @Builder
  EndCard() {
    Row() {
      if (this.END_INDEX == this.mIndex) {
        Image(this.mImageResource[this.END_INDEX])
          .BGCardCardWidthAndHeight()
          .opacity(this.mCardOpacity)
          .CardAnim()
          .borderWidth(px2vp(2))
          .borderColor(Color.Red)
          .backgroundColor(Color.Blue)

       }
    }
    .BGWidthAndHeight()
  }

  @Builder
  HeadSwiperLayerView() {
    Swiper(this.swiperController) {
      this.HeadCard()
      this.MiddenCard()
      this.EndCard()
    }
    .loop(true)
    .autoPlay(true)
    .indicator(false)
    .duration(500)
    .curve(Curve.Friction)
    .displayMode(SwiperDisplayMode.STRETCH)
    .onChange(this.monChangeCallBack)
    .onAnimationEnd(this.monAnimationEndCallBack)

  }

  @Styles
  BGWidthAndHeight(){
    .width(this.BG_WIDTH)
    .height(this.BG_HEIGHT)
  }

  @Styles
  BGCardCardWidthAndHeight(){
    .width(this.BG_CARD_WIDTH)
    .height(this.BG_CARD_HEIGHT)
    .borderWidth(px2vp(2))
    .borderColor(Color.Red)
  }

  @Styles
  CardAnim(){
    .animation({
      duration: 1000,
      tempo: 1,
      delay: 0,
      curve: Curve.Friction,
      playMode: PlayMode.Normal,
      iterations: 1
    })
  }

  build() {
    Stack({ alignContent: Alignment.Center }) {
      // 最底层卡片
      this.EndLayerView()

      // 中间层卡片
      this.MiddenLayerView()

      // 最上层swiper滑动层
      this.HeadSwiperLayerView()
    }
  }
}

入口界面类

Index.ets

dart 复制代码
import SlidingCardView from './SlidingCardView'

@Entry
@Component
struct Index {

  build() {
    Column(){
      SlidingCardView()
    }
    .width("100%")
    .height("100%")
  }
}
相关推荐
SuperHeroWu733 分钟前
【HarmonyOS】鸿蒙应用实现手机摇一摇功能
华为·harmonyos·鸿蒙·sensor·传感器·加速度·摇一摇
DC_BLOG36 分钟前
HarmonyOS-高级(四)
网络·华为·harmonyos
半夜偷删你代码37 分钟前
鸿蒙中开启关闭防截屏录屏
华为·harmonyos
Forever_Hopeful1 小时前
华为HarmonyOS NEXT 原生应用开发:鸿蒙中组件的组件状态管理、组件通信 && 组件状态管理小案例(好友录)!
华为·harmonyos
普推知产1 小时前
华为注册仙界等2字商标,如何申请2字商标!
华为·创业创新
Cynthia AI1 小时前
华为海思正式进入Wi-Fi FEM赛道?
华为
ChinaDragonDreamer3 小时前
HarmonyOS:多线程并发-Worker
harmonyos·鸿蒙
crownyouyou9 小时前
华为平板与非华为电脑多屏协同及Bug处理
华为·电脑·bug
Random_index11 小时前
#HarmonyOS篇: 学习资料
harmonyos
路-buan12 小时前
华为eNSP:VRRP的主备备份
网络·华为·智能路由器