DEV Community

kouwei qing
kouwei qing

Posted on

State Variables, Common Pages, Visible Area Change Callbacks, Parameter Reception, Drag-and-Drop Sorting Controls

[Daily HarmonyOS Next Knowledge] State Variables, Common Pages, Visible Area Change Callbacks, Parameter Reception, Drag-and-Drop Sorting Controls

1. Can @state-decorated variables in HarmonyOS be updated in a timer to refresh the UI?

Wrapping the function in a proper closure allows UI updates:

@Entry
@Component
struct Index {
  @State acSetValve: number = 0;

  aboutToAppear(): void {
    setInterval(() => {
      this.acSetValve += 200;
      console.log('hahhah' + this.acSetValve)
    }, 100)
  }

  build() {
    Row() {
      Column() {
        Text(this.acSetValve.toString())
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

2. How to create a common page in HarmonyOS for other pages to inherit and process shared logic?

Demo reference:

// Main page: FirstTest.ets
import { FirstTest2 } from "./FirstTest2"

@Entry
@Component
struct FirstTest {
  @State message1: string = 'Hello World';

  build() {
    Column() {
      Text("FirstTest:" + this.message1)
        .fontSize(25)
        .fontWeight(FontWeight.Bold)
      FirstTest2({ message2: this.message1 });
    }
  }
}

// Reusable component: FirstTest2.ets
@Component
export struct FirstTest2 {
  @State test: string = "FirstTest2"
  @Link message2: string;

  build() {
    Row() {
      Column() {
        Text("FirstTest2:" + this.test)
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
        Text("FirstTest2:" + this.message2)
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Why isn't the onVisibleAreaChange event triggered in HarmonyOS?

The onVisibleAreaChange event does not monitor component area changes caused by offset adjustments. For screen switching monitoring, use the Swiper component.

Documentation: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-swiper-V5

4. How to receive parameters passed via router.pushNamedRoute in HarmonyOS?

Use router.getParams() to receive parameters.

API link: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-router-V5#ZH-CN_TOPIC_0000001884917590__routergetparams

Demo reference:

import router from '@ohos.router';
class innerParams {
  array: number[]
  constructor(tuple: number[]) {
    this.array = tuple
  }
}

class routerParams {
  text: string
  data: innerParams
  constructor(str: string, tuple: number[]) {
    this.text = str
    this.data = new innerParams(tuple)
  }
}

@Entry
@Component
struct Router1 {
  build() {
    Column() {
      Column() {
        Text("I am Page 1").fontSize(50)
      }
      Column() {
        Button("Jump")
          .onClick(() => {
            router.pushUrl({
              url: 'pages/Router11',
              params: new routerParams('message', [123, 456, 789])
            })
          })
      }
    }
    .width('100%')
    .height('100%')
  }
}

import router from '@ohos.router';

class innerParams {
  array: number[]
  constructor(tuple: number[]) {
    this.array = tuple
  }
}

class routerParams {
  text: string
  data: innerParams
  constructor(str: string, tuple: number[]) {
    this.text = str
    this.data = new innerParams(tuple)
  }
}

@Entry
@Component
struct Router11 {
  aboutToAppear(): void {
    let s: number[] = ((router.getParams() as routerParams).data as innerParams).array
    console.log("*********:" + s);
  }
  build() {
    Column() {
      Text("123").fontSize(50)
      Row() {
        Text("33333").fontSize(50)
      }
    }
    .width('100%')
    .height('100%')
    .opacity(0.5)
    .backgroundColor(Color.Pink)
  }
}
Enter fullscreen mode Exit fullscreen mode

5. Are there utility classes for drag-and-drop sorting and control translation effects in HarmonyOS when current control data limits are insufficient?

For animation effects, refer to the following demo:

@Entry
@Component
struct AnimationPage {
  @Provide desX: number = 0;
  @Provide desY: number = 0;

  @Builder
  TabBar(index: number) {
    Column() {
      Image($r("app.media.icon"))
        .width(38)
        .height(38)
      Text(index == 1 ? "Classification" : index.toString())
    }
    .onAreaChange((oldValue: Area, newValue: Area) => {
      if (index == 1) {
        this.desX = newValue.globalPosition.x as number
        this.desY = newValue.globalPosition.y as number
      }
    })
  }

  build() {
    Column() {
      Category()
      Column() {
        Image($r("app.media.icon"))
          .width(38)
          .height(38)
      }
      .onAreaChange((oldValue: Area, newValue: Area) => {
        this.desX = newValue.globalPosition.x as number
        this.desY = newValue.globalPosition.y as number
      })
    }
    .width("100%")
    .height("100%")
  }
}

@Component
struct Category {
  @State dataList: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

  build() {
    Column() {
      Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap }) {
        ForEach(this.dataList, (item: number) => {
          ListItemComponent()
        })
      }
      .width('100%')
      .height('80%')
      .backgroundColor(Color.White)
    }
  }
}

@Observed
class AnimationBean {
  animationAppear: Boolean = false;
  id: number = -1;
}

@Component
struct ListItemComponent {
  @State animationList: AnimationBean[] = []
  static index: number = 0;
  @Consume desX: number;
  @Consume desY: number;
  @Provide orgX: number = 0;
  @Provide orgY: number = 0;

  @Builder
  BuildAnimationItem() {
    Image($r("app.media.app_icon"))
      .width(41)
      .height(41)
      .id("test")
      .onClick(() => {
        this.startAnimation();
      })
      .onAreaChange((oldValue: Area, newValue: Area) => {
        this.orgX = newValue.globalPosition.x as number
        this.orgY = newValue.globalPosition.y as number
      })
  }

  startAnimation() {
    const animation = new AnimationBean();
    animation.id = ListItemComponent.index++
    this.animationList.push(animation)
    animateTo({
      duration: 800,
      curve: Curve.FastOutLinearIn,
      onFinish: () => {
        animation.animationAppear = false;
        this.animationList = this.animationList.filter((item: AnimationBean) => {
          return item.animationAppear
        })
      }
    }, () => {
      animation.animationAppear = true;
    })
  }

  @Builder
  BuildItem() {
    Row() {
      Stack() {
        this.BuildAnimationItem()
        ForEach(this.animationList, (item: AnimationBean) => {
          AnimationChild({ item: item, AnimationView: this.BuildAnimationItem })
        }, (item: AnimationBean, index: number) => {
          return item.id.toLocaleString()
        })
      }
    }
    .width("20%")
    .height(60)
  }

  build() {
    this.BuildItem()
  }
}

@Component
struct AnimationChild {
  @ObjectLink item: AnimationBean;
  @Consume desX: number;
  @Consume desY: number;
  @Consume orgX: number;
  @Consume orgY: number;
  @BuilderParam
  AnimationView: () => void;

  build() {
    Row() {
      this.AnimationView()
    }
    .zIndex(5)
    .translate(this.item.animationAppear ? { x: (this.desX - this.orgX - 20), y: (this.desY - this.orgY) } : { x: 0 })
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)