HarmonyOS 鸿蒙Next如何实现下面这样的渐变过渡效果

HarmonyOS 鸿蒙Next如何实现下面这样的渐变过渡效果 要求:可左右滑动,滑动时两头渐变过渡效果。

图片

@ComponentV2
export struct TopFocusView {
  @Param gameArray: GameFocusItem[] = []
  @Param selectedIndex: number = 0
  @Event changeGame: (index: number, serviceCode: GameCode) => void;


  build() {
    Row() {
      this.listBuilder()
      Blank()
      this.scanBuilder()
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .width(Constants.FULL_PERCENT)
    .height(GameUtil.Game_FocusView_Height)
  }

  @Builder
  scanBuilder() {
    Row({ space: 30 }) {
      //扫码
      Image($r('app.media.game_header_scan'))
        .width(33)
        .height(33)
        .objectFit(ImageFit.Contain)
        .onClick(() => {
          this.clickScanLogin()
        })
    }
  }

  @Builder
  listBuilder() {
    Grid() {
      ForEach(this.gameArray, (item: GameFocusItem, index: number) => {
        GridItem() {
          GameFocusCell({
            cell: item,
            isSelected: index === this.selectedIndex,
            isLast: index === this.gameArray.length - 1
          })
        }
      }, (item: GameFocusItem) => JSON.stringify(item))
    }
    .scrollBar(BarState.Off)
    .columnsGap(12)
    .padding({ left: 5, right: 5 })
    .rowsTemplate('1fr')
    .width(Constants.GAME_FOCUS_WIDTH)
    .height(GameUtil.Game_FocusView_Height)
  }
}

更多关于HarmonyOS 鸿蒙Next如何实现下面这样的渐变过渡效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

开发者你好,可以使用颜色渐变和overlay来实现,实现思路以及示例demo可以参考:

  1. 创建可滚动的主页面。

  2. 利用颜色渐变通用属性,创建两端渐隐的自定义组件。

  3. 通过overlay通用属性,设置子组件为遮罩层。

@Entry
@Component
struct FadingEdge {
  private textArray: number[] = [];
  // 渐变起始和终止颜色
  @State linearGradientBegin1Color: string = Const.BEGIN_COLOR;
  @State linearGradientEnd1Color: string = Const.END_COLOR;

  @State linearGradientBegin2Color: string = Const.BEGIN_COLOR;
  @State linearGradientEnd2Color: string = Const.END_COLOR;

  aboutToAppear(): void {
    for (let i = 0; i < Const.ITEM_COUNT; i++) {
      this.textArray.push(i);
    }
  }

  build() {
    Column({ space: Const.ROOT_GAP }) {
      // 主体
      List({ space: Const.EXAMPLE_IMAGE_GAP }) {
        ForEach(this.textArray, () => {
          ListItem() {
            // 图片示例,需要替换为实际资源值
            Image($r('app.media.fadingedge_example1'))
              .width(200)
              .height(120)
              .borderRadius(8);
          };
        }, (item: number) => item.toString());
      }
      .listDirection(Axis.Horizontal)
      .width('100%')
      .height(120)
      .overlay(this.fadingOverlay())
      .edgeEffect(EdgeEffect.None)
      .scrollBar(BarState.Off)
      .onScrollStart(()=>{
        this.linearGradientBegin1Color = Const.END_COLOR;
        this.linearGradientEnd1Color = Const.BEGIN_COLOR;

        this.linearGradientBegin2Color = Const.BEGIN_COLOR;
        this.linearGradientEnd2Color = Const.END_COLOR;
      })
      .onReachStart(() => {
        this.linearGradientBegin1Color = Const.BEGIN_COLOR;
        this.linearGradientEnd1Color = Const.BEGIN_COLOR;

        this.linearGradientBegin2Color = Const.BEGIN_COLOR;
        this.linearGradientEnd2Color = Const.END_COLOR;
      })
      .onReachEnd(() => {
        this.linearGradientBegin1Color = Const.END_COLOR;
        this.linearGradientEnd1Color = Const.BEGIN_COLOR;

        this.linearGradientBegin2Color = Const.BEGIN_COLOR;
        this.linearGradientEnd2Color = Const.BEGIN_COLOR;
      });
    }
    .width('100%')
    .height('100%')
    .padding(10);
  }

  // 浮层组件
  @Builder
  fadingOverlay() {
    Column()
      .width("100%")
      .height(120)
      // TODO: 知识点: linearGradient 可以设置指定范围内的颜色渐变效果
      .linearGradient({
        angle: Const.OVERLAY_LINEAR_GRADIENT_ANGLE,
        colors: [
          [this.linearGradientBegin1Color, Const.OVERLAY_LINEAR_GRADIENT_COLOR_POS[0]],
          [this.linearGradientEnd1Color, Const.OVERLAY_LINEAR_GRADIENT_COLOR_POS[1]],
          [this.linearGradientBegin2Color, Const.OVERLAY_LINEAR_GRADIENT_COLOR_POS[2]],
          [this.linearGradientEnd2Color, Const.OVERLAY_LINEAR_GRADIENT_COLOR_POS[3]],
        ]
      })
      .animation({
        curve: Curve.Ease,
        duration: Const.DURATION
      })
      .hitTestBehavior(HitTestMode.Transparent);
  }
}

class Const {
  // 示例图片间距
  public static readonly EXAMPLE_IMAGE_GAP: number = 10;
  // 示例图片数量
  public static readonly ITEM_COUNT: number = 6;
  // 动画时长
  public static readonly DURATION: number = 220;
  // 边缘渐变起始和终止颜色
  public static readonly BEGIN_COLOR: string = '#00ffffff';
  public static readonly END_COLOR: string = '#ffffffff';
  // 根容器组件默认间距
  public static readonly ROOT_GAP: number = 20;
  // 顶部菜单栏间距
  public static readonly MENU_ITEM_SPACE: number = 5;
  // 顶部菜单栏Item中文字与图片间距
  public static readonly MENU_ITEM_COL_SPACE: number = 5;
  // 渐变角度
  public static readonly OVERLAY_LINEAR_GRADIENT_ANGLE: number = 90;
  // 渐变颜色位置
  public static readonly OVERLAY_LINEAR_GRADIENT_COLOR_POS: number[] = [0.0, 0.15, 0.85, 1.0];
  // tosat提示框持续时间
  public static readonly PROMPT_TOAST_DURATION: number = 1200;
}

更多关于HarmonyOS 鸿蒙Next如何实现下面这样的渐变过渡效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


左道方式:找UI要个渐变透明的图,放到这里。

鸿蒙Next实现渐变过渡效果主要使用ArkUI的动画能力。通过属性动画或显式动画,结合渐变组件如LinearGradient,设置起始和结束状态,利用animateTo方法实现平滑过渡。关键参数包括动画时长、缓动曲线和渐变起止颜色。具体代码涉及在组件状态变化时触发动画,控制渐变属性的插值计算。

在HarmonyOS Next中,实现可左右滑动且两端带有渐变遮罩的过渡效果,核心是结合Scroll组件的滚动事件与LinearGradient遮罩。以下是基于你代码结构的实现方案:

1. 核心思路Grid外部包裹一个Stack容器,在Stack的左右两侧叠加半透明的渐变遮罩层。遮罩的显隐或透明度通过监听Scroll的滚动位置(onScroll)进行动态控制。

2. 关键实现步骤

  • 结构调整:将原有的Grid放入Stack中,并在其前后添加用作遮罩的Row组件。
  • 渐变遮罩实现:使用LinearGradient实现从透明到背景色的渐变。
    // 左侧遮罩示例
    Row()
      .width(40)
      .height('100%')
      .background(
        new LinearGradient({
          angle: 90,
          colors: [[0xffffffff, 0.0], [0xffffffff, 1.0]] // 从透明到白色
        })
      )
    
  • 滚动监听与联动:为Grid启用滚动并添加onScroll事件,根据滚动位置计算并更新两端遮罩的透明度或显隐状态。
    @State leftMaskOpacity: number = 0 // 左侧遮罩透明度
    @State rightMaskOpacity: number = 1 // 右侧遮罩透明度
    
    Grid()
      .onScroll((xOffset: number, yOffset: number) => {
        // 计算逻辑示例:根据xOffset判断是否滚动到最左/最右
        this.leftMaskOpacity = (xOffset > 0) ? 1 : 0
        this.rightMaskOpacity = (xOffset < maxScrollOffset) ? 1 : 0
      })
    
    将计算出的状态(如this.leftMaskOpacity)通过.opacity()修饰符绑定到对应遮罩的Row上。

3. 代码调整要点 在你的listBuilder中,将GridStack包裹,并添加两个条件渲染的遮罩Row。确保Grid的宽度足够产生滚动,并正确设置onScroll逻辑以更新遮罩状态。

4. 性能与体验优化

  • 使用@State管理遮罩状态,确保UI响应。
  • 可考虑对滚动事件进行节流,避免频繁计算。
  • 渐变遮罩的宽度和颜色可根据实际视觉需求调整。

通过以上步骤,即可在滑动内容时,在滚动边界处呈现自然的渐变过渡效果,提升视觉体验。

回到顶部