HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

如何获取ArkTS状态管理框架代理前的原始对象

使用getTarget接口获取状态管理框架代理前的原始对象。

参考示例如下:

import { UIUtils } from '@kit.ArkUI';

@Observed
class UserInfo {
name: string = 'Tom';
}

@Entry
@Component
struct GetTargetDemo {
@State info: UserInfo = new UserInfo();

build() {
Column() {
Text(info.name: ${this.info.name})
Button('Change the properties of the proxy object')
.onClick(() => {
this.info.name = 'Alice'; // The Text component can refresh
})
Button('更改原始对象的属性')
.onClick(() => {
let rawInfo: UserInfo = UIUtils.getTarget(this.info);
if (rawInfo) {
rawInfo.name = 'Bob'; // The Text component cannot be refreshed
}
})
}
}
}
参考链接

getTarget接口:获取状态管理框架代理前的原始对象
https://coub.com/view/4b8gt3
https://coub.com/view/4b8gt2
https://coub.com/view/4b8gt0
https://coub.com/view/4b8gsz
https://coub.com/view/4b8gsy
https://coub.com/view/4b8gsx
https://coub.com/view/4b8gsw
https://coub.com/view/4b8gsv
https://coub.com/view/4b8gsu
https://coub.com/view/4b8gst
https://coub.com/view/4b8gss
https://coub.com/view/4b8gsr
https://coub.com/view/4b8gsq
https://coub.com/view/4b8gsp
https://coub.com/view/4b8gsl
https://coub.com/view/4b8gsk
https://coub.com/view/4b8gsh
https://coub.com/view/4b8gsg
https://coub.com/view/4b8gsf
https://coub.com/view/4b8gse
https://coub.com/view/4b8gsa
https://coub.com/view/4b8gs9
https://coub.com/view/4b8gs4
https://coub.com/view/4b8gs3
https://coub.com/view/4b8gs2
https://coub.com/view/4b8grz
https://coub.com/view/4b8grv
https://coub.com/view/4b8gru
https://coub.com/view/4b8grs
https://coub.com/view/4b8grq
https://coub.com/view/4b8gro
https://coub.com/view/4b8grn
https://coub.com/view/4b8grj
https://coub.com/view/4b8gre
https://coub.com/view/4b8grb
https://coub.com/view/4b8gr9
https://coub.com/view/4b8gr8
https://coub.com/view/4b8gr7
https://coub.com/view/4b8gr4
https://coub.com/view/4b8gqz
https://coub.com/view/4b8gqv
https://coub.com/view/4b8gqu
https://coub.com/view/4b8gqs
https://coub.com/view/4b8gqr
https://coub.com/view/4b8gqp
https://coub.com/view/4b8gqo
https://coub.com/view/4b8gqn
https://coub.com/view/4b8gqm
https://coub.com/view/4b8gql
https://coub.com/view/4b8gqi
https://coub.com/view/4b8gqf
https://coub.com/view/4b8gqc
https://coub.com/view/4b8gqa
https://coub.com/view/4b8gq8
https://coub.com/view/4b8gq6
https://coub.com/view/4b8gq4
https://coub.com/view/4b8gq2
https://coub.com/view/4b8gq0
https://coub.com/view/4b8gpx
https://coub.com/view/4b8gpp
https://coub.com/view/4b8gpn
https://coub.com/view/4b8gpm
https://coub.com/view/4b8gpl
https://coub.com/view/4b8gpi
https://coub.com/view/4b8gpf
https://coub.com/view/4b8gpa
https://coub.com/view/4b8gp9
https://coub.com/view/4b8gp6
https://coub.com/view/4b8gp5
https://coub.com/view/4b8gp3
https://coub.com/view/4b8gp1
https://coub.com/view/4b8goz
https://coub.com/view/4b8goy
https://coub.com/view/4b8gox
https://coub.com/view/4b8gov
https://coub.com/view/4b8gou
https://coub.com/view/4b8got
https://coub.com/view/4b8gos
https://coub.com/view/4b8gop
https://coub.com/view/4b8goe
https://coub.com/view/4b8god
https://coub.com/view/4b8goa
https://coub.com/view/4b8go8
https://coub.com/view/4b8go3
https://coub.com/view/4b8go0
https://coub.com/view/4b8gny
https://coub.com/view/4b8gnw
https://coub.com/view/4b8gnv
https://coub.com/view/4b8gnu
https://coub.com/view/4b8gns
https://coub.com/view/4b8gnk
https://coub.com/view/4b8gnj
https://coub.com/view/4b8gni
https://coub.com/view/4b8gnh
https://coub.com/view/4b8gnb
https://coub.com/view/4b8gna
https://coub.com/view/4b8gn9
https://coub.com/view/4b8gn7
https://coub.com/view/4b8gn2
https://coub.com/view/4b8cf1
https://coub.com/view/4b8cez
https://coub.com/view/4b8cev
https://coub.com/view/4b8ceu
https://coub.com/view/4b8cep
https://coub.com/view/4b8cen
https://coub.com/view/4b8cel
https://coub.com/view/4b8ceh
https://coub.com/view/4b8ceg
https://coub.com/view/4b8cee
https://coub.com/view/4b8ced
https://coub.com/view/4b8ceb
https://coub.com/view/4b8cea
https://coub.com/view/4b8ce8
https://coub.com/view/4b8ce6
https://coub.com/view/4b8ce5
https://coub.com/view/4b8ce4
https://coub.com/view/4b8ce2
https://coub.com/view/4b8ce1
https://coub.com/view/4b8cdz
https://coub.com/view/4b8cdx
https://coub.com/view/4b8cdw
https://coub.com/view/4b8cdv
https://coub.com/view/4b8cdu
https://coub.com/view/4b8cdt
https://coub.com/view/4b8cdr
https://coub.com/view/4b8cdq
https://coub.com/view/4b8cdp
https://coub.com/view/4b8cdo
https://coub.com/view/4b8cdn
https://coub.com/view/4b8cdm
https://coub.com/view/4b8cdl
https://coub.com/view/4b8cdk
https://coub.com/view/4b8cdj
https://coub.com/view/4b8cdi
https://coub.com/view/4b8cdh
https://coub.com/view/4b8cdf
https://coub.com/view/4b8cde
https://coub.com/view/4b8cdc
https://coub.com/view/4b8cda
https://coub.com/view/4b8cd5
https://coub.com/view/4b8cd4
https://coub.com/view/4b8cd2
https://coub.com/view/4b8cd0
https://coub.com/view/4b8ccx
https://coub.com/view/4b8ccw
https://coub.com/view/4b8ccv
https://coub.com/view/4b8ccs
https://coub.com/view/4b8ccq
https://coub.com/view/4b8ccn
https://coub.com/view/4b8ccj
https://coub.com/view/4b8cci
https://coub.com/view/4b8cca
https://coub.com/view/4b8cc3
https://coub.com/view/4b8cc1
https://coub.com/view/4b8cbz
https://coub.com/view/4b8cbw
https://coub.com/view/4b8cbt
https://coub.com/view/4b8cbl
https://coub.com/view/4b8cbk
https://coub.com/view/4b8cbh
https://coub.com/view/4b8cbf
https://coub.com/view/4b8cbe
https://coub.com/view/4b8cbd
https://coub.com/view/4b8cbb
https://coub.com/view/4b8cba
https://coub.com/view/4b8cb9
https://coub.com/view/4b8cb7
https://coub.com/view/4b8cb5
https://coub.com/view/4b8cb4
https://coub.com/view/4b8cb3
https://coub.com/view/4b8cb0
https://coub.com/view/4b8cax
https://coub.com/view/4b8caw
https://coub.com/view/4b8cau
https://coub.com/view/4b8cat
https://coub.com/view/4b8car
https://coub.com/view/4b8caq
https://coub.com/view/4b8cai
https://coub.com/view/4b8cah
https://coub.com/view/4b8caf
https://coub.com/view/4b8cae
https://coub.com/view/4b8cac
https://coub.com/view/4b8cab
https://coub.com/view/4b8caa
https://coub.com/view/4b8ca8
https://coub.com/view/4b8ca7
https://coub.com/view/4b8ca6
https://coub.com/view/4b8ca4
https://coub.com/view/4b8ca3
https://coub.com/view/4b8ca2
https://coub.com/view/4b8ca1
https://coub.com/view/4b8ca0
https://coub.com/view/4b8c9y
https://coub.com/view/4b8c9x
https://coub.com/view/4b8c9w
https://coub.com/view/4b8c9v
https://coub.com/view/4b8c9u

继续阅读 »

使用getTarget接口获取状态管理框架代理前的原始对象。

参考示例如下:

import { UIUtils } from '@kit.ArkUI';

@Observed
class UserInfo {
name: string = 'Tom';
}

@Entry
@Component
struct GetTargetDemo {
@State info: UserInfo = new UserInfo();

build() {
Column() {
Text(info.name: ${this.info.name})
Button('Change the properties of the proxy object')
.onClick(() => {
this.info.name = 'Alice'; // The Text component can refresh
})
Button('更改原始对象的属性')
.onClick(() => {
let rawInfo: UserInfo = UIUtils.getTarget(this.info);
if (rawInfo) {
rawInfo.name = 'Bob'; // The Text component cannot be refreshed
}
})
}
}
}
参考链接

getTarget接口:获取状态管理框架代理前的原始对象
https://coub.com/view/4b8gt3
https://coub.com/view/4b8gt2
https://coub.com/view/4b8gt0
https://coub.com/view/4b8gsz
https://coub.com/view/4b8gsy
https://coub.com/view/4b8gsx
https://coub.com/view/4b8gsw
https://coub.com/view/4b8gsv
https://coub.com/view/4b8gsu
https://coub.com/view/4b8gst
https://coub.com/view/4b8gss
https://coub.com/view/4b8gsr
https://coub.com/view/4b8gsq
https://coub.com/view/4b8gsp
https://coub.com/view/4b8gsl
https://coub.com/view/4b8gsk
https://coub.com/view/4b8gsh
https://coub.com/view/4b8gsg
https://coub.com/view/4b8gsf
https://coub.com/view/4b8gse
https://coub.com/view/4b8gsa
https://coub.com/view/4b8gs9
https://coub.com/view/4b8gs4
https://coub.com/view/4b8gs3
https://coub.com/view/4b8gs2
https://coub.com/view/4b8grz
https://coub.com/view/4b8grv
https://coub.com/view/4b8gru
https://coub.com/view/4b8grs
https://coub.com/view/4b8grq
https://coub.com/view/4b8gro
https://coub.com/view/4b8grn
https://coub.com/view/4b8grj
https://coub.com/view/4b8gre
https://coub.com/view/4b8grb
https://coub.com/view/4b8gr9
https://coub.com/view/4b8gr8
https://coub.com/view/4b8gr7
https://coub.com/view/4b8gr4
https://coub.com/view/4b8gqz
https://coub.com/view/4b8gqv
https://coub.com/view/4b8gqu
https://coub.com/view/4b8gqs
https://coub.com/view/4b8gqr
https://coub.com/view/4b8gqp
https://coub.com/view/4b8gqo
https://coub.com/view/4b8gqn
https://coub.com/view/4b8gqm
https://coub.com/view/4b8gql
https://coub.com/view/4b8gqi
https://coub.com/view/4b8gqf
https://coub.com/view/4b8gqc
https://coub.com/view/4b8gqa
https://coub.com/view/4b8gq8
https://coub.com/view/4b8gq6
https://coub.com/view/4b8gq4
https://coub.com/view/4b8gq2
https://coub.com/view/4b8gq0
https://coub.com/view/4b8gpx
https://coub.com/view/4b8gpp
https://coub.com/view/4b8gpn
https://coub.com/view/4b8gpm
https://coub.com/view/4b8gpl
https://coub.com/view/4b8gpi
https://coub.com/view/4b8gpf
https://coub.com/view/4b8gpa
https://coub.com/view/4b8gp9
https://coub.com/view/4b8gp6
https://coub.com/view/4b8gp5
https://coub.com/view/4b8gp3
https://coub.com/view/4b8gp1
https://coub.com/view/4b8goz
https://coub.com/view/4b8goy
https://coub.com/view/4b8gox
https://coub.com/view/4b8gov
https://coub.com/view/4b8gou
https://coub.com/view/4b8got
https://coub.com/view/4b8gos
https://coub.com/view/4b8gop
https://coub.com/view/4b8goe
https://coub.com/view/4b8god
https://coub.com/view/4b8goa
https://coub.com/view/4b8go8
https://coub.com/view/4b8go3
https://coub.com/view/4b8go0
https://coub.com/view/4b8gny
https://coub.com/view/4b8gnw
https://coub.com/view/4b8gnv
https://coub.com/view/4b8gnu
https://coub.com/view/4b8gns
https://coub.com/view/4b8gnk
https://coub.com/view/4b8gnj
https://coub.com/view/4b8gni
https://coub.com/view/4b8gnh
https://coub.com/view/4b8gnb
https://coub.com/view/4b8gna
https://coub.com/view/4b8gn9
https://coub.com/view/4b8gn7
https://coub.com/view/4b8gn2
https://coub.com/view/4b8cf1
https://coub.com/view/4b8cez
https://coub.com/view/4b8cev
https://coub.com/view/4b8ceu
https://coub.com/view/4b8cep
https://coub.com/view/4b8cen
https://coub.com/view/4b8cel
https://coub.com/view/4b8ceh
https://coub.com/view/4b8ceg
https://coub.com/view/4b8cee
https://coub.com/view/4b8ced
https://coub.com/view/4b8ceb
https://coub.com/view/4b8cea
https://coub.com/view/4b8ce8
https://coub.com/view/4b8ce6
https://coub.com/view/4b8ce5
https://coub.com/view/4b8ce4
https://coub.com/view/4b8ce2
https://coub.com/view/4b8ce1
https://coub.com/view/4b8cdz
https://coub.com/view/4b8cdx
https://coub.com/view/4b8cdw
https://coub.com/view/4b8cdv
https://coub.com/view/4b8cdu
https://coub.com/view/4b8cdt
https://coub.com/view/4b8cdr
https://coub.com/view/4b8cdq
https://coub.com/view/4b8cdp
https://coub.com/view/4b8cdo
https://coub.com/view/4b8cdn
https://coub.com/view/4b8cdm
https://coub.com/view/4b8cdl
https://coub.com/view/4b8cdk
https://coub.com/view/4b8cdj
https://coub.com/view/4b8cdi
https://coub.com/view/4b8cdh
https://coub.com/view/4b8cdf
https://coub.com/view/4b8cde
https://coub.com/view/4b8cdc
https://coub.com/view/4b8cda
https://coub.com/view/4b8cd5
https://coub.com/view/4b8cd4
https://coub.com/view/4b8cd2
https://coub.com/view/4b8cd0
https://coub.com/view/4b8ccx
https://coub.com/view/4b8ccw
https://coub.com/view/4b8ccv
https://coub.com/view/4b8ccs
https://coub.com/view/4b8ccq
https://coub.com/view/4b8ccn
https://coub.com/view/4b8ccj
https://coub.com/view/4b8cci
https://coub.com/view/4b8cca
https://coub.com/view/4b8cc3
https://coub.com/view/4b8cc1
https://coub.com/view/4b8cbz
https://coub.com/view/4b8cbw
https://coub.com/view/4b8cbt
https://coub.com/view/4b8cbl
https://coub.com/view/4b8cbk
https://coub.com/view/4b8cbh
https://coub.com/view/4b8cbf
https://coub.com/view/4b8cbe
https://coub.com/view/4b8cbd
https://coub.com/view/4b8cbb
https://coub.com/view/4b8cba
https://coub.com/view/4b8cb9
https://coub.com/view/4b8cb7
https://coub.com/view/4b8cb5
https://coub.com/view/4b8cb4
https://coub.com/view/4b8cb3
https://coub.com/view/4b8cb0
https://coub.com/view/4b8cax
https://coub.com/view/4b8caw
https://coub.com/view/4b8cau
https://coub.com/view/4b8cat
https://coub.com/view/4b8car
https://coub.com/view/4b8caq
https://coub.com/view/4b8cai
https://coub.com/view/4b8cah
https://coub.com/view/4b8caf
https://coub.com/view/4b8cae
https://coub.com/view/4b8cac
https://coub.com/view/4b8cab
https://coub.com/view/4b8caa
https://coub.com/view/4b8ca8
https://coub.com/view/4b8ca7
https://coub.com/view/4b8ca6
https://coub.com/view/4b8ca4
https://coub.com/view/4b8ca3
https://coub.com/view/4b8ca2
https://coub.com/view/4b8ca1
https://coub.com/view/4b8ca0
https://coub.com/view/4b8c9y
https://coub.com/view/4b8c9x
https://coub.com/view/4b8c9w
https://coub.com/view/4b8c9v
https://coub.com/view/4b8c9u

收起阅读 »

如何解决组件消失动画偏移闪烁

demo

问题描述

运行下面demo,点击使色块消失时,会突然出现在左上角闪烁。

@Entry
@ComponentV2
struct Index {
@Local isShow: boolean = true;

build() {
Stack() {
Stack() {
if (this.isShow) {
Row()
.width(100)
.height(100)
.backgroundColor(Color.Red)
.transition(TransitionEffect.OPACITY.animation({ duration: 150 }));
}
}
.backgroundColor(Color.Green)
}
.width('100%')
.height('100%')
.onClick(() => {
this.isShow = !this.isShow;
});
}
}
解决措施

原因是当变量置为false时,组件会从视图树中移除,导致内层Stack失去内容后位置重置到左上角,可以固定内层Stack组件的宽高来避免,示例如下:

@Entry
@ComponentV2
struct DisappearanceAnimationOffsetFlicker {
@Local isShow: boolean = true;

build() {
Stack() {
Stack() {
if (this.isShow) {
Row()
.width(100)
.height(100)
.backgroundColor(Color.Red)
.transition(TransitionEffect.OPACITY.animation({ duration: 150 }))
}
}
.width('100%')
.height('100%')
.onClick(() => {
this.isShow = !this.isShow
})
}
}
}
https://coub.com/view/4b8cf1
https://coub.com/view/4b8cez
https://coub.com/view/4b8cev
https://coub.com/view/4b8ceu
https://coub.com/view/4b8cep
https://coub.com/view/4b8cen
https://coub.com/view/4b8cel
https://coub.com/view/4b8ceh
https://coub.com/view/4b8ceg
https://coub.com/view/4b8cee
https://coub.com/view/4b8ced
https://coub.com/view/4b8ceb
https://coub.com/view/4b8cea
https://coub.com/view/4b8ce8
https://coub.com/view/4b8ce6
https://coub.com/view/4b8ce5
https://coub.com/view/4b8ce4
https://coub.com/view/4b8ce2
https://coub.com/view/4b8ce1
https://coub.com/view/4b8cdz
https://coub.com/view/4b8cdx
https://coub.com/view/4b8cdw
https://coub.com/view/4b8cdv
https://coub.com/view/4b8cdu
https://coub.com/view/4b8cdt
https://coub.com/view/4b8cdr
https://coub.com/view/4b8cdq
https://coub.com/view/4b8cdp
https://coub.com/view/4b8cdo
https://coub.com/view/4b8cdn
https://coub.com/view/4b8cdm
https://coub.com/view/4b8cdl
https://coub.com/view/4b8cdk
https://coub.com/view/4b8cdj
https://coub.com/view/4b8cdi
https://coub.com/view/4b8cdh
https://coub.com/view/4b8cdf
https://coub.com/view/4b8cde
https://coub.com/view/4b8cdc
https://coub.com/view/4b8cda
https://coub.com/view/4b8cd5
https://coub.com/view/4b8cd4
https://coub.com/view/4b8cd2
https://coub.com/view/4b8cd0
https://coub.com/view/4b8ccx
https://coub.com/view/4b8ccw
https://coub.com/view/4b8ccv
https://coub.com/view/4b8ccs
https://coub.com/view/4b8ccq
https://coub.com/view/4b8ccn
https://coub.com/view/4b8ccj
https://coub.com/view/4b8cci
https://coub.com/view/4b8cca
https://coub.com/view/4b8cc3
https://coub.com/view/4b8cc1
https://coub.com/view/4b8cbz
https://coub.com/view/4b8cbw
https://coub.com/view/4b8cbt
https://coub.com/view/4b8cbl
https://coub.com/view/4b8cbk
https://coub.com/view/4b8cbh
https://coub.com/view/4b8cbf
https://coub.com/view/4b8cbe
https://coub.com/view/4b8cbd
https://coub.com/view/4b8cbb
https://coub.com/view/4b8cba
https://coub.com/view/4b8cb9
https://coub.com/view/4b8cb7
https://coub.com/view/4b8cb5
https://coub.com/view/4b8cb4
https://coub.com/view/4b8cb3
https://coub.com/view/4b8cb0
https://coub.com/view/4b8cax
https://coub.com/view/4b8caw
https://coub.com/view/4b8cau
https://coub.com/view/4b8cat
https://coub.com/view/4b8car
https://coub.com/view/4b8caq
https://coub.com/view/4b8cai
https://coub.com/view/4b8cah
https://coub.com/view/4b8caf
https://coub.com/view/4b8cae
https://coub.com/view/4b8cac
https://coub.com/view/4b8cab
https://coub.com/view/4b8caa
https://coub.com/view/4b8ca8
https://coub.com/view/4b8ca7
https://coub.com/view/4b8ca6
https://coub.com/view/4b8ca4
https://coub.com/view/4b8ca3
https://coub.com/view/4b8ca2
https://coub.com/view/4b8ca1
https://coub.com/view/4b8ca0
https://coub.com/view/4b8c9y
https://coub.com/view/4b8c9x
https://coub.com/view/4b8c9w
https://coub.com/view/4b8c9v
https://coub.com/view/4b8c9u

https://coub.com/view/4b87sb
https://coub.com/view/4b7yjg
https://coub.com/view/4b7yjf
https://coub.com/view/4b7yjd
https://coub.com/view/4b7yiw
https://coub.com/view/4b7yis
https://coub.com/view/4b7yip
https://coub.com/view/4b7yik
https://coub.com/view/4b7yij
https://coub.com/view/4b7yig
https://coub.com/view/4b7yie
https://coub.com/view/4b7yic
https://coub.com/view/4b7yia
https://coub.com/view/4b7yi7
https://coub.com/view/4b7yi5
https://coub.com/view/4b7yi3
https://coub.com/view/4b7yhy
https://coub.com/view/4b7yht
https://coub.com/view/4b7yhr
https://coub.com/view/4b7yhp
https://coub.com/view/4b7yhh
https://coub.com/view/4b7yhg
https://coub.com/view/4b7yhf
https://coub.com/view/4b7yhb
https://coub.com/view/4b7yh9
https://coub.com/view/4b7yh6
https://coub.com/view/4b7yh4
https://coub.com/view/4b7ygz
https://coub.com/view/4b7ygx
https://coub.com/view/4b7ygu
https://coub.com/view/4b7ygr
https://coub.com/view/4b7ygn
https://coub.com/view/4b7ygk
https://coub.com/view/4b7ygh
https://coub.com/view/4b7ygf
https://coub.com/view/4b7ygd
https://coub.com/view/4b7ygb
https://coub.com/view/4b7yg8
https://coub.com/view/4b7yg5
https://coub.com/view/4b7yg2
https://coub.com/view/4b7yfr
https://coub.com/view/4b7yfo
https://coub.com/view/4b7yfk
https://coub.com/view/4b7yfh
https://coub.com/view/4b7yfe
https://coub.com/view/4b7yfc
https://coub.com/view/4b7yfa
https://coub.com/view/4b7yf7
https://coub.com/view/4b7yf5
https://coub.com/view/4b7yf1
https://coub.com/view/4b7yez
https://coub.com/view/4b7yet
https://coub.com/view/4b7yer
https://coub.com/view/4b7yep
https://coub.com/view/4b7yeo
https://coub.com/view/4b7ub4
https://coub.com/view/4b7ub3
https://coub.com/view/4b7ub2
https://coub.com/view/4b7ub0
https://coub.com/view/4b7uay
https://coub.com/view/4b7uax
https://coub.com/view/4b7uav
https://coub.com/view/4b7uap
https://coub.com/view/4b7uao
https://coub.com/view/4b7ual
https://coub.com/view/4b7uad
https://coub.com/view/4b7uaa
https://coub.com/view/4b7ua7
https://coub.com/view/4b7ua5
https://coub.com/view/4b7ua2
https://coub.com/view/4b7ua1
https://coub.com/view/4b7u9z
https://coub.com/view/4b7u9y
https://coub.com/view/4b7u9x
https://coub.com/view/4b7u9p
https://coub.com/view/4b7u9k
https://coub.com/view/4b7u9j
https://coub.com/view/4b7u9i
https://coub.com/view/4b7u9g
https://coub.com/view/4b7u9d
https://coub.com/view/4b7u9a
https://coub.com/view/4b7u98
https://coub.com/view/4b7u96
https://coub.com/view/4b7u94
https://coub.com/view/4b7u92
https://coub.com/view/4b7u91
https://coub.com/view/4b7u8z
https://coub.com/view/4b7u8t
https://coub.com/view/4b7u8q
https://coub.com/view/4b7u8p
https://coub.com/view/4b7u8n
https://coub.com/view/4b7u8j
https://coub.com/view/4b7u8i
https://coub.com/view/4b7u78
https://coub.com/view/4b7u76
https://coub.com/view/4b7u72
https://coub.com/view/4b7u6v
https://coub.com/view/4b7u6t
https://coub.com/view/4b7u6r
https://coub.com/view/4b7u6o
https://coub.com/view/4b7u6m
https://coub.com/view/4b7u6l
https://coub.com/view/4b7u6j
https://coub.com/view/4b7u6h
https://coub.com/view/4b7u6f
https://coub.com/view/4b7u6d
https://coub.com/view/4b7u6a
https://coub.com/view/4b7u67
https://coub.com/view/4b7u65
https://coub.com/view/4b7u60
https://coub.com/view/4b7u5t
https://coub.com/view/4b7u5p
https://coub.com/view/4b7u5i
https://coub.com/view/4b7u4t
https://coub.com/view/4b7u4p
https://coub.com/view/4b7u4l
https://coub.com/view/4b7u46
https://coub.com/view/4b7u3v
https://coub.com/view/4b7u3u
https://coub.com/view/4b7u3t
https://coub.com/view/4b7u3r
https://coub.com/view/4b7u3o
https://coub.com/view/4b7u3l
https://coub.com/view/4b7u3k
https://coub.com/view/4b7u3h
https://coub.com/view/4b7u3a
https://coub.com/view/4b7u38
https://coub.com/view/4b7u35
https://coub.com/view/4b7u34
https://coub.com/view/4b7u33
https://coub.com/view/4b7u30
https://coub.com/view/4b7u2z
https://coub.com/view/4b7u2w

继续阅读 »

问题描述

运行下面demo,点击使色块消失时,会突然出现在左上角闪烁。

@Entry
@ComponentV2
struct Index {
@Local isShow: boolean = true;

build() {
Stack() {
Stack() {
if (this.isShow) {
Row()
.width(100)
.height(100)
.backgroundColor(Color.Red)
.transition(TransitionEffect.OPACITY.animation({ duration: 150 }));
}
}
.backgroundColor(Color.Green)
}
.width('100%')
.height('100%')
.onClick(() => {
this.isShow = !this.isShow;
});
}
}
解决措施

原因是当变量置为false时,组件会从视图树中移除,导致内层Stack失去内容后位置重置到左上角,可以固定内层Stack组件的宽高来避免,示例如下:

@Entry
@ComponentV2
struct DisappearanceAnimationOffsetFlicker {
@Local isShow: boolean = true;

build() {
Stack() {
Stack() {
if (this.isShow) {
Row()
.width(100)
.height(100)
.backgroundColor(Color.Red)
.transition(TransitionEffect.OPACITY.animation({ duration: 150 }))
}
}
.width('100%')
.height('100%')
.onClick(() => {
this.isShow = !this.isShow
})
}
}
}
https://coub.com/view/4b8cf1
https://coub.com/view/4b8cez
https://coub.com/view/4b8cev
https://coub.com/view/4b8ceu
https://coub.com/view/4b8cep
https://coub.com/view/4b8cen
https://coub.com/view/4b8cel
https://coub.com/view/4b8ceh
https://coub.com/view/4b8ceg
https://coub.com/view/4b8cee
https://coub.com/view/4b8ced
https://coub.com/view/4b8ceb
https://coub.com/view/4b8cea
https://coub.com/view/4b8ce8
https://coub.com/view/4b8ce6
https://coub.com/view/4b8ce5
https://coub.com/view/4b8ce4
https://coub.com/view/4b8ce2
https://coub.com/view/4b8ce1
https://coub.com/view/4b8cdz
https://coub.com/view/4b8cdx
https://coub.com/view/4b8cdw
https://coub.com/view/4b8cdv
https://coub.com/view/4b8cdu
https://coub.com/view/4b8cdt
https://coub.com/view/4b8cdr
https://coub.com/view/4b8cdq
https://coub.com/view/4b8cdp
https://coub.com/view/4b8cdo
https://coub.com/view/4b8cdn
https://coub.com/view/4b8cdm
https://coub.com/view/4b8cdl
https://coub.com/view/4b8cdk
https://coub.com/view/4b8cdj
https://coub.com/view/4b8cdi
https://coub.com/view/4b8cdh
https://coub.com/view/4b8cdf
https://coub.com/view/4b8cde
https://coub.com/view/4b8cdc
https://coub.com/view/4b8cda
https://coub.com/view/4b8cd5
https://coub.com/view/4b8cd4
https://coub.com/view/4b8cd2
https://coub.com/view/4b8cd0
https://coub.com/view/4b8ccx
https://coub.com/view/4b8ccw
https://coub.com/view/4b8ccv
https://coub.com/view/4b8ccs
https://coub.com/view/4b8ccq
https://coub.com/view/4b8ccn
https://coub.com/view/4b8ccj
https://coub.com/view/4b8cci
https://coub.com/view/4b8cca
https://coub.com/view/4b8cc3
https://coub.com/view/4b8cc1
https://coub.com/view/4b8cbz
https://coub.com/view/4b8cbw
https://coub.com/view/4b8cbt
https://coub.com/view/4b8cbl
https://coub.com/view/4b8cbk
https://coub.com/view/4b8cbh
https://coub.com/view/4b8cbf
https://coub.com/view/4b8cbe
https://coub.com/view/4b8cbd
https://coub.com/view/4b8cbb
https://coub.com/view/4b8cba
https://coub.com/view/4b8cb9
https://coub.com/view/4b8cb7
https://coub.com/view/4b8cb5
https://coub.com/view/4b8cb4
https://coub.com/view/4b8cb3
https://coub.com/view/4b8cb0
https://coub.com/view/4b8cax
https://coub.com/view/4b8caw
https://coub.com/view/4b8cau
https://coub.com/view/4b8cat
https://coub.com/view/4b8car
https://coub.com/view/4b8caq
https://coub.com/view/4b8cai
https://coub.com/view/4b8cah
https://coub.com/view/4b8caf
https://coub.com/view/4b8cae
https://coub.com/view/4b8cac
https://coub.com/view/4b8cab
https://coub.com/view/4b8caa
https://coub.com/view/4b8ca8
https://coub.com/view/4b8ca7
https://coub.com/view/4b8ca6
https://coub.com/view/4b8ca4
https://coub.com/view/4b8ca3
https://coub.com/view/4b8ca2
https://coub.com/view/4b8ca1
https://coub.com/view/4b8ca0
https://coub.com/view/4b8c9y
https://coub.com/view/4b8c9x
https://coub.com/view/4b8c9w
https://coub.com/view/4b8c9v
https://coub.com/view/4b8c9u

https://coub.com/view/4b87sb
https://coub.com/view/4b7yjg
https://coub.com/view/4b7yjf
https://coub.com/view/4b7yjd
https://coub.com/view/4b7yiw
https://coub.com/view/4b7yis
https://coub.com/view/4b7yip
https://coub.com/view/4b7yik
https://coub.com/view/4b7yij
https://coub.com/view/4b7yig
https://coub.com/view/4b7yie
https://coub.com/view/4b7yic
https://coub.com/view/4b7yia
https://coub.com/view/4b7yi7
https://coub.com/view/4b7yi5
https://coub.com/view/4b7yi3
https://coub.com/view/4b7yhy
https://coub.com/view/4b7yht
https://coub.com/view/4b7yhr
https://coub.com/view/4b7yhp
https://coub.com/view/4b7yhh
https://coub.com/view/4b7yhg
https://coub.com/view/4b7yhf
https://coub.com/view/4b7yhb
https://coub.com/view/4b7yh9
https://coub.com/view/4b7yh6
https://coub.com/view/4b7yh4
https://coub.com/view/4b7ygz
https://coub.com/view/4b7ygx
https://coub.com/view/4b7ygu
https://coub.com/view/4b7ygr
https://coub.com/view/4b7ygn
https://coub.com/view/4b7ygk
https://coub.com/view/4b7ygh
https://coub.com/view/4b7ygf
https://coub.com/view/4b7ygd
https://coub.com/view/4b7ygb
https://coub.com/view/4b7yg8
https://coub.com/view/4b7yg5
https://coub.com/view/4b7yg2
https://coub.com/view/4b7yfr
https://coub.com/view/4b7yfo
https://coub.com/view/4b7yfk
https://coub.com/view/4b7yfh
https://coub.com/view/4b7yfe
https://coub.com/view/4b7yfc
https://coub.com/view/4b7yfa
https://coub.com/view/4b7yf7
https://coub.com/view/4b7yf5
https://coub.com/view/4b7yf1
https://coub.com/view/4b7yez
https://coub.com/view/4b7yet
https://coub.com/view/4b7yer
https://coub.com/view/4b7yep
https://coub.com/view/4b7yeo
https://coub.com/view/4b7ub4
https://coub.com/view/4b7ub3
https://coub.com/view/4b7ub2
https://coub.com/view/4b7ub0
https://coub.com/view/4b7uay
https://coub.com/view/4b7uax
https://coub.com/view/4b7uav
https://coub.com/view/4b7uap
https://coub.com/view/4b7uao
https://coub.com/view/4b7ual
https://coub.com/view/4b7uad
https://coub.com/view/4b7uaa
https://coub.com/view/4b7ua7
https://coub.com/view/4b7ua5
https://coub.com/view/4b7ua2
https://coub.com/view/4b7ua1
https://coub.com/view/4b7u9z
https://coub.com/view/4b7u9y
https://coub.com/view/4b7u9x
https://coub.com/view/4b7u9p
https://coub.com/view/4b7u9k
https://coub.com/view/4b7u9j
https://coub.com/view/4b7u9i
https://coub.com/view/4b7u9g
https://coub.com/view/4b7u9d
https://coub.com/view/4b7u9a
https://coub.com/view/4b7u98
https://coub.com/view/4b7u96
https://coub.com/view/4b7u94
https://coub.com/view/4b7u92
https://coub.com/view/4b7u91
https://coub.com/view/4b7u8z
https://coub.com/view/4b7u8t
https://coub.com/view/4b7u8q
https://coub.com/view/4b7u8p
https://coub.com/view/4b7u8n
https://coub.com/view/4b7u8j
https://coub.com/view/4b7u8i
https://coub.com/view/4b7u78
https://coub.com/view/4b7u76
https://coub.com/view/4b7u72
https://coub.com/view/4b7u6v
https://coub.com/view/4b7u6t
https://coub.com/view/4b7u6r
https://coub.com/view/4b7u6o
https://coub.com/view/4b7u6m
https://coub.com/view/4b7u6l
https://coub.com/view/4b7u6j
https://coub.com/view/4b7u6h
https://coub.com/view/4b7u6f
https://coub.com/view/4b7u6d
https://coub.com/view/4b7u6a
https://coub.com/view/4b7u67
https://coub.com/view/4b7u65
https://coub.com/view/4b7u60
https://coub.com/view/4b7u5t
https://coub.com/view/4b7u5p
https://coub.com/view/4b7u5i
https://coub.com/view/4b7u4t
https://coub.com/view/4b7u4p
https://coub.com/view/4b7u4l
https://coub.com/view/4b7u46
https://coub.com/view/4b7u3v
https://coub.com/view/4b7u3u
https://coub.com/view/4b7u3t
https://coub.com/view/4b7u3r
https://coub.com/view/4b7u3o
https://coub.com/view/4b7u3l
https://coub.com/view/4b7u3k
https://coub.com/view/4b7u3h
https://coub.com/view/4b7u3a
https://coub.com/view/4b7u38
https://coub.com/view/4b7u35
https://coub.com/view/4b7u34
https://coub.com/view/4b7u33
https://coub.com/view/4b7u30
https://coub.com/view/4b7u2z
https://coub.com/view/4b7u2w

收起阅读 »

如何实现背景以圆弧形式向外扩展的翻页动画效果

问题现象
如何实现一种翻页动画效果,其中背景以圆弧形式逐步扩大,同时文字向左下方放大并移动?

背景知识
Stack:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
createAnimator:定义Animator类,可以设置动画播放时长、插值曲线等参数。
解决方案
可通过帧动画实现页面转场效果,具体步骤如下:

定义两个Page组件,分别用于展示不同的页面内容。
class PageContent {
content: string;
style: TextStyle;

constructor(content: string, style: TextStyle = {}) {
this.content = content;
this.style = style;
}
}
配置页面切换时的动画。
this.animator = this.getUIContext().createAnimator({
duration: 500,
easing: 'ease',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: 1,
begin: 0, //动画插值起点
end: 500 //动画插值终点
});
this.animator.onFrame = progress => {
this.pageController[0].onFrame?.(progress / 500, this.currentIndex === 1);
this.pageController[1].onFrame?.(progress / 500, this.currentIndex === 0);
};
this.animator.onFinish = () => {
let lastIndex = this.currentIndex;
this.currentIndex = 1 - this.currentIndex;
this.zIndexList[lastIndex] = 1;
this.zIndexList[this.currentIndex] = 0;
this.isAnimating = false;
};
使用Stack布局将两个页面组件堆叠显示。
Stack({ alignContent: Alignment.TopStart }) {
Page({
content: page1Content,
bgColor: '#000',
scaleValue: 1,
controller: this.pageController[0],
isShow: true
})
.zIndex(this.zIndexList[0])
.onClick(() => {
this.handleClick();
});
Page({
content: page2Content,
bgColor: '#fff',
scaleValue: 0.01,
controller: this.pageController[1]
})
.zIndex(this.zIndexList[1])
.onClick(() => {
this.handleClick();
});
}
.width('100%')
.height('100%')
.id('root')
.clip(true);
在用户点击右上角圆形按钮时,触发动画切换。
handleClick() {
if (this.isAnimating) {
return;
}
this.isAnimating = true;
this.animator?.play();
}
完整示例代码如下:

import { AnimatorResult } from '@kit.ArkUI';

class PageContent {
content: string;
style: TextStyle;

constructor(content: string, style: TextStyle = {}) {
this.content = content;
this.style = style;
}
}

const page1Content: PageContent[] = [
new PageContent('Hello everyone, I`am very happy to tell you hello world ',
{ fontSize: 30, fontWeight: 700, fontColor: Color.White }),
new PageContent('The text component is used to display a piece of textual information.Support universal attributes and universal text attributes.',
{ fontColor: Color.White }),
new PageContent('This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content. This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content.',
{ fontColor: Color.White }),
];

const page2Content: PageContent[] = [
new PageContent('Hello everyone, Please say hello! ', { fontSize: 30 }),
new PageContent('Nice to meet you.', { fontSize: 30 }),
new PageContent('I`m fine thank you and you.', { fontSize: 30 }),
new PageContent('No problem.', { fontSize: 30 }),
];

interface PageInfo {
width: number,
height: number,
centerX: number,
centerY: number
}

class PageController {
push?: (onFinish: () => void) => void;
pop?: (onFinish: () => void) => void;
onFrame?: (progress: number, isPush: boolean) => void;
}

@Entry
@Component
export struct TransitionPage {
@Provide info: PageInfo = {
width: 0,
height: 0,
centerX: 0,
centerY: 0
};
pageController: PageController[] = [];
@State zIndexList: number[] = [];
private isAnimating: boolean = false;
private animator?: AnimatorResult;
private currentIndex: number = 0;

aboutToAppear(): void {
let observer = this.getUIContext().getUIInspector().createComponentObserver('root');
observer.on('layout', () => {
let node = this.getUIContext().getAttachedFrameNodeById('root');
if (node) {
this.info = {
width: this.getUIContext().px2vp(node.getMeasuredSize().width),
height: this.getUIContext().px2vp(node.getMeasuredSize().height),
centerY: 50,
centerX: this.getUIContext().px2vp(node.getMeasuredSize().width) - 40
};
}
});
for (let i = 0; i < 2; i++) {
this.pageController.push(new PageController());
this.zIndexList.push(i);
}
// 页面切换时的动画
this.animator = this.getUIContext().createAnimator({
duration: 500,
easing: 'ease',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: 1,
begin: 0, //动画插值起点
end: 500 //动画插值终点
});
this.animator.onFrame = progress => {
this.pageController[0].onFrame?.(progress / 500, this.currentIndex === 1);
this.pageController[1].onFrame?.(progress / 500, this.currentIndex === 0);
};
this.animator.onFinish = () => {
let lastIndex = this.currentIndex;
this.currentIndex = 1 - this.currentIndex;
this.zIndexList[lastIndex] = 1;
this.zIndexList[this.currentIndex] = 0;
this.isAnimating = false;
};
}

aboutToDisappear(): void {
this.animator?.finish();
this.animator = undefined;
}

push(index: number) {
let promise: Promise<void>[] = [];
promise.push(new Promise(resolve => {
this.pageController[index].push?.(() => {
this.zIndexList[index] = 0;
resolve();
});
}));
let lastIndex = 1 - index;
promise.push(new Promise(resolve => {
this.pageController[lastIndex].pop?.(() => {
this.zIndexList[lastIndex] = 1;
resolve();
});
}));
Promise.all(promise).then(() => this.isAnimating = false);
}
// 动画切换事件
handleClick() {
if (this.isAnimating) {
return;
}
this.isAnimating = true;
this.animator?.play();
}

build() {
// 两个页面组件堆叠显示
Stack({ alignContent: Alignment.TopStart }) {
Page({
content: page1Content,
bgColor: '#000',
scaleValue: 1,
controller: this.pageController[0],
isShow: true
})
.zIndex(this.zIndexList[0])
.onClick(() => {
this.handleClick();
});
Page({
content: page2Content,
bgColor: '#fff',
scaleValue: 0.01,
controller: this.pageController[1]
})
.zIndex(this.zIndexList[1])
.onClick(() => {
this.handleClick();
});
}
.width('100%')
.height('100%')
.id('root')
.clip(true);
}

onDidBuild(): void {
if (!this.animator) {
return;
}
}
}

@Component
struct Page {
@Require content: PageContent[] = [];
@Consume @Watch('onInit') info: PageInfo;
@State scaleValue: number = 0.01;
@State r: number = 0;
@State isShow: boolean = false;
bgColor: string = '#fff';
controller?: PageController;

onInit() {
this.r = Math.sqrt(this.info.centerX this.info.centerX +
(this.info.height - this.info.centerY)
(this.info.height - this.info.centerY));
}

aboutToAppear(): void {
if (this.controller) {
this.controller.push = (onFinish) => {
this.onPush(onFinish);
};
this.controller.pop = (onFinish) => {
this.onPop(onFinish);
};
this.controller.onFrame = (progress, isPush) => {
if (isPush) {
this.isShow = true;
this.scaleValue = 0.01 + (1 - 0.01) progress;
} else {
this.scaleValue = 1 + (4 - 1)
progress;
if (progress >= 1) {
this.isShow = false;
this.scaleValue = 0.01;
}
}
};
}
}

onPush(onFinish: () => void) {
this.isShow = true;
this.getUIContext().animateTo({ duration: 500, onFinish: onFinish }, () => {
this.scaleValue = 1;
});
}

onPop(onFinish: () => void) {
this.getUIContext().animateTo({
duration: 500,
onFinish: () => {
this.scaleValue = 0.01;
this.isShow = false;
onFinish();
}
}, () => {
this.scaleValue = 4;
});
}

build() {
Column() {
if (this.isShow) {
Column({ space: 20 }) {
ForEach(this.content, (item: PageContent) => {
Text(item.content)
.fontSize(item.style.fontSize)
.fontColor(item.style.fontColor)
.fontWeight(item.style.fontWeight)
.fontStyle(item.style.fontStyle)
.fontFamily(item.style.fontFamily);
});
}
.position({ x: this.r - this.info.centerX, y: this.r - this.info.centerY })
.padding({ left: 16, right:16 })
.width(this.info.width)
.height(this.info.height)
.justifyContent(FlexAlign.SpaceEvenly);
}
}
.width(this.r 2)
.height(this.r
2)
.constraintSize({ minWidth: this.r * 2 })
.scale({ x: this.scaleValue, y: this.scaleValue })
.offset({ x: this.info.centerX - this.r, y: this.info.centerY - this.r })
.borderRadius(this.r)
.clip(true)
.backgroundColor(this.bgColor);
}
}
https://coub.com/view/4b7yjg
https://coub.com/view/4b7yjf
https://coub.com/view/4b7yjd
https://coub.com/view/4b7yiw
https://coub.com/view/4b7yis
https://coub.com/view/4b7yip
https://coub.com/view/4b7yik
https://coub.com/view/4b7yij
https://coub.com/view/4b7yig
https://coub.com/view/4b7yie
https://coub.com/view/4b7yic
https://coub.com/view/4b7yia
https://coub.com/view/4b7yi7
https://coub.com/view/4b7yi5
https://coub.com/view/4b7yi3
https://coub.com/view/4b7yhy
https://coub.com/view/4b7yht
https://coub.com/view/4b7yhr
https://coub.com/view/4b7yhp
https://coub.com/view/4b7yhh
https://coub.com/view/4b7yhg
https://coub.com/view/4b7yhf
https://coub.com/view/4b7yhb
https://coub.com/view/4b7yh9
https://coub.com/view/4b7yh6
https://coub.com/view/4b7yh4
https://coub.com/view/4b7ygz
https://coub.com/view/4b7ygx
https://coub.com/view/4b7ygu
https://coub.com/view/4b7ygr
https://coub.com/view/4b7ygn
https://coub.com/view/4b7ygk
https://coub.com/view/4b7ygh
https://coub.com/view/4b7ygf
https://coub.com/view/4b7ygd
https://coub.com/view/4b7ygb
https://coub.com/view/4b7yg8
https://coub.com/view/4b7yg5
https://coub.com/view/4b7yg2
https://coub.com/view/4b7yfr
https://coub.com/view/4b7yfo
https://coub.com/view/4b7yfk
https://coub.com/view/4b7yfh
https://coub.com/view/4b7yfe
https://coub.com/view/4b7yfc
https://coub.com/view/4b7yfa
https://coub.com/view/4b7yf7
https://coub.com/view/4b7yf5
https://coub.com/view/4b7yf1
https://coub.com/view/4b7yez
https://coub.com/view/4b7yet
https://coub.com/view/4b7yer
https://coub.com/view/4b7yep
https://coub.com/view/4b7yeo
https://coub.com/view/4b7ub4
https://coub.com/view/4b7ub3
https://coub.com/view/4b7ub2
https://coub.com/view/4b7ub0
https://coub.com/view/4b7uay
https://coub.com/view/4b7uax
https://coub.com/view/4b7uav
https://coub.com/view/4b7uap
https://coub.com/view/4b7uao
https://coub.com/view/4b7ual
https://coub.com/view/4b7uad
https://coub.com/view/4b7uaa
https://coub.com/view/4b7ua7
https://coub.com/view/4b7ua5
https://coub.com/view/4b7ua2
https://coub.com/view/4b7ua1
https://coub.com/view/4b7u9z
https://coub.com/view/4b7u9y
https://coub.com/view/4b7u9x
https://coub.com/view/4b7u9p
https://coub.com/view/4b7u9k
https://coub.com/view/4b7u9j
https://coub.com/view/4b7u9i
https://coub.com/view/4b7u9g
https://coub.com/view/4b7u9d
https://coub.com/view/4b7u9a
https://coub.com/view/4b7u98
https://coub.com/view/4b7u96
https://coub.com/view/4b7u94
https://coub.com/view/4b7u92
https://coub.com/view/4b7u91
https://coub.com/view/4b7u8z
https://coub.com/view/4b7u8t
https://coub.com/view/4b7u8q
https://coub.com/view/4b7u8p
https://coub.com/view/4b7u8n
https://coub.com/view/4b7u8j
https://coub.com/view/4b7u8i
https://coub.com/view/4b7u78
https://coub.com/view/4b7u76
https://coub.com/view/4b7u72
https://coub.com/view/4b7u6v
https://coub.com/view/4b7u6t
https://coub.com/view/4b7u6r
https://coub.com/view/4b7u6o
https://coub.com/view/4b7u6m
https://coub.com/view/4b7u6l
https://coub.com/view/4b7u6j
https://coub.com/view/4b7u6h
https://coub.com/view/4b7u6f
https://coub.com/view/4b7u6d
https://coub.com/view/4b7u6a
https://coub.com/view/4b7u67
https://coub.com/view/4b7u65
https://coub.com/view/4b7u60
https://coub.com/view/4b7u5t
https://coub.com/view/4b7u5p
https://coub.com/view/4b7u5i
https://coub.com/view/4b7u4t
https://coub.com/view/4b7u4p
https://coub.com/view/4b7u4l
https://coub.com/view/4b7u46
https://coub.com/view/4b7u3v
https://coub.com/view/4b7u3u
https://coub.com/view/4b7u3t
https://coub.com/view/4b7u3r
https://coub.com/view/4b7u3o
https://coub.com/view/4b7u3l
https://coub.com/view/4b7u3k
https://coub.com/view/4b7u3h
https://coub.com/view/4b7u3a
https://coub.com/view/4b7u38
https://coub.com/view/4b7u35
https://coub.com/view/4b7u34
https://coub.com/view/4b7u33
https://coub.com/view/4b7u30
https://coub.com/view/4b7u2z
https://coub.com/view/4b7u2w

继续阅读 »

问题现象
如何实现一种翻页动画效果,其中背景以圆弧形式逐步扩大,同时文字向左下方放大并移动?

背景知识
Stack:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
createAnimator:定义Animator类,可以设置动画播放时长、插值曲线等参数。
解决方案
可通过帧动画实现页面转场效果,具体步骤如下:

定义两个Page组件,分别用于展示不同的页面内容。
class PageContent {
content: string;
style: TextStyle;

constructor(content: string, style: TextStyle = {}) {
this.content = content;
this.style = style;
}
}
配置页面切换时的动画。
this.animator = this.getUIContext().createAnimator({
duration: 500,
easing: 'ease',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: 1,
begin: 0, //动画插值起点
end: 500 //动画插值终点
});
this.animator.onFrame = progress => {
this.pageController[0].onFrame?.(progress / 500, this.currentIndex === 1);
this.pageController[1].onFrame?.(progress / 500, this.currentIndex === 0);
};
this.animator.onFinish = () => {
let lastIndex = this.currentIndex;
this.currentIndex = 1 - this.currentIndex;
this.zIndexList[lastIndex] = 1;
this.zIndexList[this.currentIndex] = 0;
this.isAnimating = false;
};
使用Stack布局将两个页面组件堆叠显示。
Stack({ alignContent: Alignment.TopStart }) {
Page({
content: page1Content,
bgColor: '#000',
scaleValue: 1,
controller: this.pageController[0],
isShow: true
})
.zIndex(this.zIndexList[0])
.onClick(() => {
this.handleClick();
});
Page({
content: page2Content,
bgColor: '#fff',
scaleValue: 0.01,
controller: this.pageController[1]
})
.zIndex(this.zIndexList[1])
.onClick(() => {
this.handleClick();
});
}
.width('100%')
.height('100%')
.id('root')
.clip(true);
在用户点击右上角圆形按钮时,触发动画切换。
handleClick() {
if (this.isAnimating) {
return;
}
this.isAnimating = true;
this.animator?.play();
}
完整示例代码如下:

import { AnimatorResult } from '@kit.ArkUI';

class PageContent {
content: string;
style: TextStyle;

constructor(content: string, style: TextStyle = {}) {
this.content = content;
this.style = style;
}
}

const page1Content: PageContent[] = [
new PageContent('Hello everyone, I`am very happy to tell you hello world ',
{ fontSize: 30, fontWeight: 700, fontColor: Color.White }),
new PageContent('The text component is used to display a piece of textual information.Support universal attributes and universal text attributes.',
{ fontColor: Color.White }),
new PageContent('This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content. This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content.',
{ fontColor: Color.White }),
];

const page2Content: PageContent[] = [
new PageContent('Hello everyone, Please say hello! ', { fontSize: 30 }),
new PageContent('Nice to meet you.', { fontSize: 30 }),
new PageContent('I`m fine thank you and you.', { fontSize: 30 }),
new PageContent('No problem.', { fontSize: 30 }),
];

interface PageInfo {
width: number,
height: number,
centerX: number,
centerY: number
}

class PageController {
push?: (onFinish: () => void) => void;
pop?: (onFinish: () => void) => void;
onFrame?: (progress: number, isPush: boolean) => void;
}

@Entry
@Component
export struct TransitionPage {
@Provide info: PageInfo = {
width: 0,
height: 0,
centerX: 0,
centerY: 0
};
pageController: PageController[] = [];
@State zIndexList: number[] = [];
private isAnimating: boolean = false;
private animator?: AnimatorResult;
private currentIndex: number = 0;

aboutToAppear(): void {
let observer = this.getUIContext().getUIInspector().createComponentObserver('root');
observer.on('layout', () => {
let node = this.getUIContext().getAttachedFrameNodeById('root');
if (node) {
this.info = {
width: this.getUIContext().px2vp(node.getMeasuredSize().width),
height: this.getUIContext().px2vp(node.getMeasuredSize().height),
centerY: 50,
centerX: this.getUIContext().px2vp(node.getMeasuredSize().width) - 40
};
}
});
for (let i = 0; i < 2; i++) {
this.pageController.push(new PageController());
this.zIndexList.push(i);
}
// 页面切换时的动画
this.animator = this.getUIContext().createAnimator({
duration: 500,
easing: 'ease',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: 1,
begin: 0, //动画插值起点
end: 500 //动画插值终点
});
this.animator.onFrame = progress => {
this.pageController[0].onFrame?.(progress / 500, this.currentIndex === 1);
this.pageController[1].onFrame?.(progress / 500, this.currentIndex === 0);
};
this.animator.onFinish = () => {
let lastIndex = this.currentIndex;
this.currentIndex = 1 - this.currentIndex;
this.zIndexList[lastIndex] = 1;
this.zIndexList[this.currentIndex] = 0;
this.isAnimating = false;
};
}

aboutToDisappear(): void {
this.animator?.finish();
this.animator = undefined;
}

push(index: number) {
let promise: Promise<void>[] = [];
promise.push(new Promise(resolve => {
this.pageController[index].push?.(() => {
this.zIndexList[index] = 0;
resolve();
});
}));
let lastIndex = 1 - index;
promise.push(new Promise(resolve => {
this.pageController[lastIndex].pop?.(() => {
this.zIndexList[lastIndex] = 1;
resolve();
});
}));
Promise.all(promise).then(() => this.isAnimating = false);
}
// 动画切换事件
handleClick() {
if (this.isAnimating) {
return;
}
this.isAnimating = true;
this.animator?.play();
}

build() {
// 两个页面组件堆叠显示
Stack({ alignContent: Alignment.TopStart }) {
Page({
content: page1Content,
bgColor: '#000',
scaleValue: 1,
controller: this.pageController[0],
isShow: true
})
.zIndex(this.zIndexList[0])
.onClick(() => {
this.handleClick();
});
Page({
content: page2Content,
bgColor: '#fff',
scaleValue: 0.01,
controller: this.pageController[1]
})
.zIndex(this.zIndexList[1])
.onClick(() => {
this.handleClick();
});
}
.width('100%')
.height('100%')
.id('root')
.clip(true);
}

onDidBuild(): void {
if (!this.animator) {
return;
}
}
}

@Component
struct Page {
@Require content: PageContent[] = [];
@Consume @Watch('onInit') info: PageInfo;
@State scaleValue: number = 0.01;
@State r: number = 0;
@State isShow: boolean = false;
bgColor: string = '#fff';
controller?: PageController;

onInit() {
this.r = Math.sqrt(this.info.centerX this.info.centerX +
(this.info.height - this.info.centerY)
(this.info.height - this.info.centerY));
}

aboutToAppear(): void {
if (this.controller) {
this.controller.push = (onFinish) => {
this.onPush(onFinish);
};
this.controller.pop = (onFinish) => {
this.onPop(onFinish);
};
this.controller.onFrame = (progress, isPush) => {
if (isPush) {
this.isShow = true;
this.scaleValue = 0.01 + (1 - 0.01) progress;
} else {
this.scaleValue = 1 + (4 - 1)
progress;
if (progress >= 1) {
this.isShow = false;
this.scaleValue = 0.01;
}
}
};
}
}

onPush(onFinish: () => void) {
this.isShow = true;
this.getUIContext().animateTo({ duration: 500, onFinish: onFinish }, () => {
this.scaleValue = 1;
});
}

onPop(onFinish: () => void) {
this.getUIContext().animateTo({
duration: 500,
onFinish: () => {
this.scaleValue = 0.01;
this.isShow = false;
onFinish();
}
}, () => {
this.scaleValue = 4;
});
}

build() {
Column() {
if (this.isShow) {
Column({ space: 20 }) {
ForEach(this.content, (item: PageContent) => {
Text(item.content)
.fontSize(item.style.fontSize)
.fontColor(item.style.fontColor)
.fontWeight(item.style.fontWeight)
.fontStyle(item.style.fontStyle)
.fontFamily(item.style.fontFamily);
});
}
.position({ x: this.r - this.info.centerX, y: this.r - this.info.centerY })
.padding({ left: 16, right:16 })
.width(this.info.width)
.height(this.info.height)
.justifyContent(FlexAlign.SpaceEvenly);
}
}
.width(this.r 2)
.height(this.r
2)
.constraintSize({ minWidth: this.r * 2 })
.scale({ x: this.scaleValue, y: this.scaleValue })
.offset({ x: this.info.centerX - this.r, y: this.info.centerY - this.r })
.borderRadius(this.r)
.clip(true)
.backgroundColor(this.bgColor);
}
}
https://coub.com/view/4b7yjg
https://coub.com/view/4b7yjf
https://coub.com/view/4b7yjd
https://coub.com/view/4b7yiw
https://coub.com/view/4b7yis
https://coub.com/view/4b7yip
https://coub.com/view/4b7yik
https://coub.com/view/4b7yij
https://coub.com/view/4b7yig
https://coub.com/view/4b7yie
https://coub.com/view/4b7yic
https://coub.com/view/4b7yia
https://coub.com/view/4b7yi7
https://coub.com/view/4b7yi5
https://coub.com/view/4b7yi3
https://coub.com/view/4b7yhy
https://coub.com/view/4b7yht
https://coub.com/view/4b7yhr
https://coub.com/view/4b7yhp
https://coub.com/view/4b7yhh
https://coub.com/view/4b7yhg
https://coub.com/view/4b7yhf
https://coub.com/view/4b7yhb
https://coub.com/view/4b7yh9
https://coub.com/view/4b7yh6
https://coub.com/view/4b7yh4
https://coub.com/view/4b7ygz
https://coub.com/view/4b7ygx
https://coub.com/view/4b7ygu
https://coub.com/view/4b7ygr
https://coub.com/view/4b7ygn
https://coub.com/view/4b7ygk
https://coub.com/view/4b7ygh
https://coub.com/view/4b7ygf
https://coub.com/view/4b7ygd
https://coub.com/view/4b7ygb
https://coub.com/view/4b7yg8
https://coub.com/view/4b7yg5
https://coub.com/view/4b7yg2
https://coub.com/view/4b7yfr
https://coub.com/view/4b7yfo
https://coub.com/view/4b7yfk
https://coub.com/view/4b7yfh
https://coub.com/view/4b7yfe
https://coub.com/view/4b7yfc
https://coub.com/view/4b7yfa
https://coub.com/view/4b7yf7
https://coub.com/view/4b7yf5
https://coub.com/view/4b7yf1
https://coub.com/view/4b7yez
https://coub.com/view/4b7yet
https://coub.com/view/4b7yer
https://coub.com/view/4b7yep
https://coub.com/view/4b7yeo
https://coub.com/view/4b7ub4
https://coub.com/view/4b7ub3
https://coub.com/view/4b7ub2
https://coub.com/view/4b7ub0
https://coub.com/view/4b7uay
https://coub.com/view/4b7uax
https://coub.com/view/4b7uav
https://coub.com/view/4b7uap
https://coub.com/view/4b7uao
https://coub.com/view/4b7ual
https://coub.com/view/4b7uad
https://coub.com/view/4b7uaa
https://coub.com/view/4b7ua7
https://coub.com/view/4b7ua5
https://coub.com/view/4b7ua2
https://coub.com/view/4b7ua1
https://coub.com/view/4b7u9z
https://coub.com/view/4b7u9y
https://coub.com/view/4b7u9x
https://coub.com/view/4b7u9p
https://coub.com/view/4b7u9k
https://coub.com/view/4b7u9j
https://coub.com/view/4b7u9i
https://coub.com/view/4b7u9g
https://coub.com/view/4b7u9d
https://coub.com/view/4b7u9a
https://coub.com/view/4b7u98
https://coub.com/view/4b7u96
https://coub.com/view/4b7u94
https://coub.com/view/4b7u92
https://coub.com/view/4b7u91
https://coub.com/view/4b7u8z
https://coub.com/view/4b7u8t
https://coub.com/view/4b7u8q
https://coub.com/view/4b7u8p
https://coub.com/view/4b7u8n
https://coub.com/view/4b7u8j
https://coub.com/view/4b7u8i
https://coub.com/view/4b7u78
https://coub.com/view/4b7u76
https://coub.com/view/4b7u72
https://coub.com/view/4b7u6v
https://coub.com/view/4b7u6t
https://coub.com/view/4b7u6r
https://coub.com/view/4b7u6o
https://coub.com/view/4b7u6m
https://coub.com/view/4b7u6l
https://coub.com/view/4b7u6j
https://coub.com/view/4b7u6h
https://coub.com/view/4b7u6f
https://coub.com/view/4b7u6d
https://coub.com/view/4b7u6a
https://coub.com/view/4b7u67
https://coub.com/view/4b7u65
https://coub.com/view/4b7u60
https://coub.com/view/4b7u5t
https://coub.com/view/4b7u5p
https://coub.com/view/4b7u5i
https://coub.com/view/4b7u4t
https://coub.com/view/4b7u4p
https://coub.com/view/4b7u4l
https://coub.com/view/4b7u46
https://coub.com/view/4b7u3v
https://coub.com/view/4b7u3u
https://coub.com/view/4b7u3t
https://coub.com/view/4b7u3r
https://coub.com/view/4b7u3o
https://coub.com/view/4b7u3l
https://coub.com/view/4b7u3k
https://coub.com/view/4b7u3h
https://coub.com/view/4b7u3a
https://coub.com/view/4b7u38
https://coub.com/view/4b7u35
https://coub.com/view/4b7u34
https://coub.com/view/4b7u33
https://coub.com/view/4b7u30
https://coub.com/view/4b7u2z
https://coub.com/view/4b7u2w

收起阅读 »

如何解决Navigation路由调用pop后onPop回调代码不执行的问题

问题现象
使用Navigation构建路由,从pageOne通过pushPath跳转到pageTwo,期望pageOne的onPop回调在pageTwo返回时被触发,但效果未达预期。

问题代码示例参考如下:

class ParamWithOp {
operation: number = 1
count: number = 10
}

@Entry
@Component
struct PageOne {
pageInfo: NavPathStack = new NavPathStack();
@State message: string = 'Hello World'

@Builder
pageMap(name: string, params: Object) {
if (name === 'pageTwo') {
PageTwo()
}
}

build() {
Navigation(this.pageInfo) {
Column() {
Text(this.message)
.width('80%')
.height(50)
.margin(10)

    Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })  
      .width('80%')  
      .height(40)  
      .margin(10)  
      .onClick(() => {  
        // 将name指定的NavDestination页面信息入栈,传递的数据为param,添加接收处理结果的onPop回调。  
        this.pageInfo.pushPath({  
          name: 'pageTwo', param: new ParamWithOp(), onPop: (popInfo: PopInfo) => {  
            this.message = `[pushPath]last page is: ${popInfo.info.name} result: ${JSON.stringify(popInfo.result)}`  
          }  
        });  
      })  
  }.width('100%').height('100%')  
}.navDestination(this.pageMap)  
.title('pageOne')  

}
}

@Component
struct PageTwo {
pathStack: NavPathStack = new NavPathStack()

build() {
NavDestination() {
Column() {
Button('pop', { stateEffect: true, type: ButtonType.Capsule })
.width('80%')
.height(40)
.margin(20)
.onClick(() => {
// 回退到上一个页面,此处代码,在pop回pageOne页面时,未传参数
this.pathStack.pop();
})
}.width('100%').height('100%')
}.title('pageTwo')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
效果预览
点击放大

背景知识
Navigation组件是路由导航的根视图容器,结合导航控制器NavPathStack可实现组件导航。

pushPath:将info指定的NavDestination页面信息入栈。可设置onPop回调函数来接收参数。
pop:弹出路由栈栈顶元素,并触发onPop回调传入页面处理结果。
问题定位
点击放大

查阅官方文档关于pushPath方法的NavPathInfo入参说明,其中的onPop回调函数仅pop、popToName、popToIndex中设置result参数后触发。

分析结论
onPop回调函数需要使用pop、popToName、popToIndex方法返回时设置result参数才会触发,否则不会执行onPop回调。

修改建议
按上节所述,只需在pageTwo中调用pop方法时,传入result参数,即可在pageOne中成功收到onPop的回调。修改问题代码如下:

// 回退到上一个页面,随便传个result即可触发onPop回调
this.pathStack.pop(1);
修改后的运行效果参见效果预览,可以看到,当pageTwo调用pop返回时传入了result参数,在pageOne成功执行了onPop回调,并接收到相关参数。
https://coub.com/stories/5089704-jcu
https://coub.com/stories/5089703-griffith
https://coub.com/stories/5089702-uq
https://coub.com/stories/5089700-swinburne
https://coub.com/view/4b73k6
https://coub.com/view/4b73k4
https://coub.com/view/4b73k3
https://coub.com/view/4b73k2
https://coub.com/view/4b73k1
https://coub.com/view/4b73jz
https://coub.com/view/4b73jw
https://coub.com/view/4b73jv
https://coub.com/view/4b73js
https://coub.com/view/4b73jp
https://coub.com/view/4b73jm
https://coub.com/view/4b73jj
https://coub.com/view/4b73ji
https://coub.com/view/4b73jh
https://coub.com/view/4b73jg
https://coub.com/sources/19155990
https://coub.com/sources/19155989
https://coub.com/sources/19155987
https://coub.com/view/4b73j9
https://coub.com/view/4b73j7
https://coub.com/stories/5089696-victoria
https://coub.com/stories/5089695-flinders
https://coub.com/stories/5089694-unisa
https://coub.com/stories/5089693-uc
https://coub.com/stories/5089691-cdu
https://coub.com/stories/5089689-curtin
https://coub.com/stories/5089687-bond
https://coub.com/stories/5089686-jcu
https://coub.com/stories/5089684-cqu
https://coub.com/view/4b707t
https://coub.com/view/4b707r
https://coub.com/view/4b707o
https://coub.com/view/4b707n
https://coub.com/view/4b707h
https://coub.com/view/4b707d
https://coub.com/view/4b7077
https://coub.com/view/4b7074
https://coub.com/view/4b706z
https://coub.com/view/4b706u
https://coub.com/view/4b706o
https://coub.com/view/4b706c
https://coub.com/view/4b7063
https://coub.com/view/4b7060
https://coub.com/view/4b705v
https://coub.com/view/4b705n
https://coub.com/view/4b705k
https://coub.com/view/4b701z
https://coub.com/view/4b6zjc
https://coub.com/view/4b6zja
https://coub.com/view/4b6zj9
https://coub.com/view/4b6zj6
https://coub.com/view/4b6zj4
https://coub.com/view/4b6zj3
https://coub.com/view/4b6zj2
https://coub.com/view/4b6zj1
https://coub.com/view/4b6ziz
https://coub.com/view/4b6zix
https://coub.com/view/4b6ziv
https://coub.com/view/4b6ziu
https://coub.com/view/4b6zit
https://coub.com/view/4b6zis
https://coub.com/view/4b6zio
https://coub.com/view/4b6zin
https://coub.com/view/4b6zim
https://coub.com/view/4b6zik

继续阅读 »

问题现象
使用Navigation构建路由,从pageOne通过pushPath跳转到pageTwo,期望pageOne的onPop回调在pageTwo返回时被触发,但效果未达预期。

问题代码示例参考如下:

class ParamWithOp {
operation: number = 1
count: number = 10
}

@Entry
@Component
struct PageOne {
pageInfo: NavPathStack = new NavPathStack();
@State message: string = 'Hello World'

@Builder
pageMap(name: string, params: Object) {
if (name === 'pageTwo') {
PageTwo()
}
}

build() {
Navigation(this.pageInfo) {
Column() {
Text(this.message)
.width('80%')
.height(50)
.margin(10)

    Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })  
      .width('80%')  
      .height(40)  
      .margin(10)  
      .onClick(() => {  
        // 将name指定的NavDestination页面信息入栈,传递的数据为param,添加接收处理结果的onPop回调。  
        this.pageInfo.pushPath({  
          name: 'pageTwo', param: new ParamWithOp(), onPop: (popInfo: PopInfo) => {  
            this.message = `[pushPath]last page is: ${popInfo.info.name} result: ${JSON.stringify(popInfo.result)}`  
          }  
        });  
      })  
  }.width('100%').height('100%')  
}.navDestination(this.pageMap)  
.title('pageOne')  

}
}

@Component
struct PageTwo {
pathStack: NavPathStack = new NavPathStack()

build() {
NavDestination() {
Column() {
Button('pop', { stateEffect: true, type: ButtonType.Capsule })
.width('80%')
.height(40)
.margin(20)
.onClick(() => {
// 回退到上一个页面,此处代码,在pop回pageOne页面时,未传参数
this.pathStack.pop();
})
}.width('100%').height('100%')
}.title('pageTwo')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
效果预览
点击放大

背景知识
Navigation组件是路由导航的根视图容器,结合导航控制器NavPathStack可实现组件导航。

pushPath:将info指定的NavDestination页面信息入栈。可设置onPop回调函数来接收参数。
pop:弹出路由栈栈顶元素,并触发onPop回调传入页面处理结果。
问题定位
点击放大

查阅官方文档关于pushPath方法的NavPathInfo入参说明,其中的onPop回调函数仅pop、popToName、popToIndex中设置result参数后触发。

分析结论
onPop回调函数需要使用pop、popToName、popToIndex方法返回时设置result参数才会触发,否则不会执行onPop回调。

修改建议
按上节所述,只需在pageTwo中调用pop方法时,传入result参数,即可在pageOne中成功收到onPop的回调。修改问题代码如下:

// 回退到上一个页面,随便传个result即可触发onPop回调
this.pathStack.pop(1);
修改后的运行效果参见效果预览,可以看到,当pageTwo调用pop返回时传入了result参数,在pageOne成功执行了onPop回调,并接收到相关参数。
https://coub.com/stories/5089704-jcu
https://coub.com/stories/5089703-griffith
https://coub.com/stories/5089702-uq
https://coub.com/stories/5089700-swinburne
https://coub.com/view/4b73k6
https://coub.com/view/4b73k4
https://coub.com/view/4b73k3
https://coub.com/view/4b73k2
https://coub.com/view/4b73k1
https://coub.com/view/4b73jz
https://coub.com/view/4b73jw
https://coub.com/view/4b73jv
https://coub.com/view/4b73js
https://coub.com/view/4b73jp
https://coub.com/view/4b73jm
https://coub.com/view/4b73jj
https://coub.com/view/4b73ji
https://coub.com/view/4b73jh
https://coub.com/view/4b73jg
https://coub.com/sources/19155990
https://coub.com/sources/19155989
https://coub.com/sources/19155987
https://coub.com/view/4b73j9
https://coub.com/view/4b73j7
https://coub.com/stories/5089696-victoria
https://coub.com/stories/5089695-flinders
https://coub.com/stories/5089694-unisa
https://coub.com/stories/5089693-uc
https://coub.com/stories/5089691-cdu
https://coub.com/stories/5089689-curtin
https://coub.com/stories/5089687-bond
https://coub.com/stories/5089686-jcu
https://coub.com/stories/5089684-cqu
https://coub.com/view/4b707t
https://coub.com/view/4b707r
https://coub.com/view/4b707o
https://coub.com/view/4b707n
https://coub.com/view/4b707h
https://coub.com/view/4b707d
https://coub.com/view/4b7077
https://coub.com/view/4b7074
https://coub.com/view/4b706z
https://coub.com/view/4b706u
https://coub.com/view/4b706o
https://coub.com/view/4b706c
https://coub.com/view/4b7063
https://coub.com/view/4b7060
https://coub.com/view/4b705v
https://coub.com/view/4b705n
https://coub.com/view/4b705k
https://coub.com/view/4b701z
https://coub.com/view/4b6zjc
https://coub.com/view/4b6zja
https://coub.com/view/4b6zj9
https://coub.com/view/4b6zj6
https://coub.com/view/4b6zj4
https://coub.com/view/4b6zj3
https://coub.com/view/4b6zj2
https://coub.com/view/4b6zj1
https://coub.com/view/4b6ziz
https://coub.com/view/4b6zix
https://coub.com/view/4b6ziv
https://coub.com/view/4b6ziu
https://coub.com/view/4b6zit
https://coub.com/view/4b6zis
https://coub.com/view/4b6zio
https://coub.com/view/4b6zin
https://coub.com/view/4b6zim
https://coub.com/view/4b6zik

收起阅读 »

如何解决拖拽功能和长按功能的冲突问题

问题现象
在List组件中,单个ListItem在同时设置拖拽功能与长按功能时,实际运行之后会产生冲突,如何解决单个ListItem拖拽功能和长按功能的冲突问题?

效果预览
点击放大

背景知识
支持统一拖拽提供了一种通过鼠标或手势触屏传递数据的机制,即从一个组件位置拖出数据并将其拖入到另一个组件位置,以触发响应。
长按手势通过长按屏幕触发长按手势事件。
由于拖拽事件和长按手势都需要通过长按来触发,因此这种组合手势类型会出现冲突,例如List组件中每个ListItem都设置单独的长按事件时,拖拽功能和长按手势功能就会出现冲突。
Grid网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。
滑动手势PanGesture,能够提供自定义拖拽事件的功能。
解决方案
由于在ListItem中设置单独的长按事件会与拖拽事件产生冲突,因此建议放弃List本身的拖拽事件,使用滑动手势PanGesture,自行实现拖拽过程的逻辑,然后再通过组合手势的功能,去实现其他的长按事件。
import curves from '@ohos.curves';

@Entry
@Component
struct Page {
// 元素数组
@State numbers: number[] = [];
// 多列
private str: string = '';
row: number = 4;
// 元素数组中最后一个元素的索引
@State lastIndex: number = 0;
@State dragItem: number = -1;
@State scaleItem: number = -1;
item: number = -1;
private dragRefOffsetX: number = 0;
private dragRefOffsetY: number = 0;
@State offsetX: number = 0;
@State offsetY: number = 0;
private FIX_VP_X: number = 108;
private FIX_VP_Y: number = 120;

aboutToAppear() {
for (let i = 1; i <= 36; i++) {
this.numbers.push(i);
}
this.lastIndex = this.numbers.length - 1;
// 多列
for (let i = 0; i < this.row; i++) {
this.str = this.str + '1fr ';
}
}

itemMove(index: number, newIndex: number): void {
console.info('index:' + index + ' newIndex:' + newIndex);
if (!this.isDraggable(newIndex)) {
return;
}
let tmp = this.numbers.splice(index, 1);
this.numbers.splice(newIndex, 0, tmp[0]);
}

// 向下滑
down(index: number): void {
if (!this.isDraggable(index + this.row)) {
return;
}
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
// 多列
this.itemMove(index, index + this.row);
}

// 向下滑(右下角为空)
down2(index: number): void {
if (!this.isDraggable(index + 3)) {
return;
}
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + 3);
}

// 向上滑
up(index: number): void {
if (!this.isDraggable(index - this.row)) {
return;
}
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - this.row);
}

// 向左滑
left(index: number): void {
if (!this.isDraggable(index - 1)) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.itemMove(index, index - 1);
}

// 向右滑
right(index: number): void {
if (!this.isDraggable(index + 1)) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.itemMove(index, index + 1);
}

// 向右下滑
lowerRight(index: number): void {
if (!this.isDraggable(index + this.row + 1)) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + this.row + 1);
}

// 向右上滑
upperRight(index: number): void {
if (!this.isDraggable(index - (this.row - 1))) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - (this.row - 1));
}

// 向左下滑
lowerLeft(index: number): void {
if (!this.isDraggable(index + (this.row - 1))) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + (this.row - 1));
}

// 向左上滑
upperLeft(index: number): void {
if (!this.isDraggable(index - (this.row + 1))) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - (this.row + 1));
}

// 通过元素的索引,控制对应元素是否能移动排序
isDraggable(index: number): boolean {
console.info(index: ${index});
return index > -1; // 恒成立,所有元素均可移动排序
}
https://pastebin.com/FQ7caXPg
https://pastebin.com/qrG8cLtE
https://pastebin.com/NDkKX7GA
https://pastebin.com/v7SbJUa2
https://pastebin.com/ckwh85Uv
https://pastebin.com/FyQiZnSa
https://pastebin.com/eJTdnrt3
https://pastebin.com/FSynV6Lb
https://pastebin.com/DAj2WRVR
https://pastebin.com/2Y0LWg8C
https://pastebin.com/U3rE0GN7
https://pastebin.com/5SqdHMZn
https://pastebin.com/3vZs9u6Y
https://pastebin.com/6SHV25A8
https://pastebin.com/cxcm4039
https://pastebin.com/Rgdfcp9d
https://pastebin.com/g8Thr4Mg
https://pastebin.com/rmwrNJji
https://pastebin.com/yKbAsYCa
https://pastebin.com/dRdM2X9u
https://pastebin.com/ecff1hqL
https://pastebin.com/UGKhTWQ8
https://pastebin.com/s5hexmMG
https://pastebin.com/vixNaxtq
https://pastebin.com/jM99sFyZ
https://pastebin.com/enua3UEF
https://pastebin.com/d0QccunL
https://pastebin.com/NW6ahtVi
https://pastebin.com/HdFmVJDd
https://pastebin.com/dvqz627c
https://pastebin.com/2dkeMADC
https://pastebin.com/H61nZMVs
https://pastebin.com/VAJYkWis
https://pastebin.com/3Y7xVCzF
https://pastebin.com/XWH0bcEB
https://pastebin.com/0yZbjU38
https://pastebin.com/KT9GU4Xj
https://pastebin.com/6JyqmT7e
https://pastebin.com/3fFG8u4J
https://pastebin.com/jLbepB1x
https://pastebin.com/fcqxvaXX
https://pastebin.com/3yKQCFzT
https://pastebin.com/Gpz5Yc8A
https://pastebin.com/KUjNqvfq
https://pastebin.com/JRp0SxQ5
https://pastebin.com/dAeJ7KxQ
https://pastebin.com/Y59qi6iT
https://pastebin.com/hsBpJYrt
https://pastebin.com/2wNNccE8
https://pastebin.com/dHCqmGeK
https://pastebin.com/5zYAQpvu
https://pastebin.com/dN3bshkc
https://pastebin.com/cFSUYDNN
https://pastebin.com/yWKUSPZz
https://pastebin.com/pjyMPVgp
https://pastebin.com/iASRBbGz
https://pastebin.com/zrVfHyC0
https://pastebin.com/Lg6i3qBs
https://pastebin.com/C9y6bEfC
https://pastebin.com/3xhPr5Uz
https://pastebin.com/u6fHcaUM
https://pastebin.com/GTjsW1uh
https://pastebin.com/15xfuW7r
https://pastebin.com/ATU9sQ6v
https://pastebin.com/a2mCY3Zz
https://pastebin.com/ntnWiFcr
https://pastebin.com/AH45r30t
https://pastebin.com/H0AQ1Dww
https://pastebin.com/diHn40ki
https://pastebin.com/CZH3ckGE
https://pastebin.com/UxAfGRQt
https://pastebin.com/FLNsUiG0
https://pastebin.com/AAWktRKj
https://pastebin.com/sKm7XvTE
https://pastebin.com/gvp4Q7sh
https://pastebin.com/xuCUMBur
https://pastebin.com/2espHLP1
https://pastebin.com/64pjxFAc
https://pastebin.com/J5fQPN5U
https://pastebin.com/J0rJg6DX
https://pastebin.com/QtWnkBDp
https://pastebin.com/SeGa4TkD
https://pastebin.com/WTwjcNN1
https://pastebin.com/MAqkmJXT
https://pastebin.com/sct8XVCM
https://pastebin.com/hkT7CqNH
https://pastebin.com/f7pCY395
https://pastebin.com/ZSbSpbL6
https://pastebin.com/Ug0RKLfK
https://pastebin.com/CV8Ercz3
https://pastebin.com/guYntd9W
https://pastebin.com/Dz3vpsZz
https://pastebin.com/0QCcxGWy
https://pastebin.com/Nd37dhtk
https://pastebin.com/yf59y43d
https://pastebin.com/nj7W9tyx
https://pastebin.com/5JCZtmRJ
https://pastebin.com/wagqVUtS
https://pastebin.com/1X65Yjc3
https://pastebin.com/TtXircBz
https://pastebin.com/fTwWHfEe
https://pastebin.com/zYrag51J
https://pastebin.com/E9icvGyK
https://pastebin.com/2cXwRAxL
https://pastebin.com/w0GGQRhc
https://pastebin.com/53sfuRZK
https://pastebin.com/90uQ7V15
https://pastebin.com/ghzaUYMF
https://pastebin.com/Nnpgvdes
https://pastebin.com/Y8tuCtaz
https://pastebin.com/iWx1huat
https://pastebin.com/FdQgitkv
https://pastebin.com/8amig0td
https://pastebin.com/yzcTvFfu
https://pastebin.com/68HwXpv5
https://pastebin.com/KLAWLeKM
https://pastebin.com/dMUbkzF2
https://pastebin.com/g6rLz6au
https://pastebin.com/trd44WK2
https://pastebin.com/cQ8audPK
https://pastebin.com/wRuQcX47
https://pastebin.com/nyzk75PP
https://pastebin.com/a52FLwqg
https://pastebin.com/ifwAEKs8
https://pastebin.com/7hsBC6eM
https://pastebin.com/pLAWFQ8U
https://pastebin.com/j70c8uBX
https://pastebin.com/ymKQsh4f
https://pastebin.com/4dqNaX6T
https://pastebin.com/HSdANUrQ
https://pastebin.com/Nh8sivuq
https://pastebin.com/q55w0w2i
https://pastebin.com/wXf37h3E
https://pastebin.com/RhAxX63P
https://pastebin.com/
https://pastebin.com/d0ftXeii
https://pastebin.com/w7cKXeMc
https://pastebin.com/vJQZ8zzg
https://pastebin.com/NV6uSXAB
https://pastebin.com/aDZckQqR
https://pastebin.com/LECR3S3x
https://pastebin.com/cp78R0ry
https://pastebin.com/WD0P7hDC
https://pastebin.com/iA0h7MsB
https://pastebin.com/509YHhv2
https://pastebin.com/sR22DfaA
https://pastebin.com/fkwWBgB1
https://pastebin.com/xu1tZaib
https://pastebin.com/0e9mbjm1
https://pastebin.com/8ygNAi7Q
https://pastebin.com/q10N4BVV
https://pastebin.com/E5a1VSUL
https://pastebin.com/N4rt7xkq
https://pastebin.com/KLKahxYp
https://pastebin.com/aAhka9TS
https://pastebin.com/cFzzqVdL
https://pastebin.com/TdF2uE9H
https://pastebin.com/sAwMjAbi
https://pastebin.com/DZNFtzZq
https://pastebin.com/tHjy4Dqz
https://pastebin.com/7nGK9sVT
https://pastebin.com/uh2XxG80
https://pastebin.com/AnR5ZVHR
https://pastebin.com/Y3RLNXTu
https://pastebin.com/H1QvABLE
https://pastebin.com/gu3H4ZCC
https://pastebin.com/6stL1Xpp
https://pastebin.com/yx5inydp
https://pastebin.com/hyiiCV2A
https://pastebin.com/rgCkSxnQ
https://pastebin.com/smR119Kz
https://pastebin.com/H6GguYti
https://pastebin.com/zMupz2e0
https://pastebin.com/hA0jPvEB
https://pastebin.com/a617mt5H
https://pastebin.com/nkjG08Fw
https://pastebin.com/k6NKap1G
https://pastebin.com/mmiNsmtC
https://pastebin.com/i6V5V5dz
https://pastebin.com/GUvCDwNE
https://pastebin.com/Cd7LEAAE
https://pastebin.com/uN4xeDXm
https://pastebin.com/WT2yyehE
https://pastebin.com/3qxa54xX
https://pastebin.com/xdnPSK9i
https://pastebin.com/EEpWrErg
https://pastebin.com/MbUH0ZVm
https://pastebin.com/UfRH2vMY
https://pastebin.com/qcmM4qiM
https://pastebin.com/0NXAxPQR
https://pastebin.com/bXmTJhyf
https://pastebin.com/716Zr85T
https://pastebin.com/X0JFDTJ0
https://pastebin.com/gSc7vpdF
https://pastebin.com/LKUU1kbW
https://pastebin.com/XfbRxeZ7
https://pastebin.com/afMDqP8e
https://pastebin.com/QxJgJX0x
https://pastebin.com/WGrQcNAF
https://pastebin.com/Kbj0zKmQ

继续阅读 »

问题现象
在List组件中,单个ListItem在同时设置拖拽功能与长按功能时,实际运行之后会产生冲突,如何解决单个ListItem拖拽功能和长按功能的冲突问题?

效果预览
点击放大

背景知识
支持统一拖拽提供了一种通过鼠标或手势触屏传递数据的机制,即从一个组件位置拖出数据并将其拖入到另一个组件位置,以触发响应。
长按手势通过长按屏幕触发长按手势事件。
由于拖拽事件和长按手势都需要通过长按来触发,因此这种组合手势类型会出现冲突,例如List组件中每个ListItem都设置单独的长按事件时,拖拽功能和长按手势功能就会出现冲突。
Grid网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。
滑动手势PanGesture,能够提供自定义拖拽事件的功能。
解决方案
由于在ListItem中设置单独的长按事件会与拖拽事件产生冲突,因此建议放弃List本身的拖拽事件,使用滑动手势PanGesture,自行实现拖拽过程的逻辑,然后再通过组合手势的功能,去实现其他的长按事件。
import curves from '@ohos.curves';

@Entry
@Component
struct Page {
// 元素数组
@State numbers: number[] = [];
// 多列
private str: string = '';
row: number = 4;
// 元素数组中最后一个元素的索引
@State lastIndex: number = 0;
@State dragItem: number = -1;
@State scaleItem: number = -1;
item: number = -1;
private dragRefOffsetX: number = 0;
private dragRefOffsetY: number = 0;
@State offsetX: number = 0;
@State offsetY: number = 0;
private FIX_VP_X: number = 108;
private FIX_VP_Y: number = 120;

aboutToAppear() {
for (let i = 1; i <= 36; i++) {
this.numbers.push(i);
}
this.lastIndex = this.numbers.length - 1;
// 多列
for (let i = 0; i < this.row; i++) {
this.str = this.str + '1fr ';
}
}

itemMove(index: number, newIndex: number): void {
console.info('index:' + index + ' newIndex:' + newIndex);
if (!this.isDraggable(newIndex)) {
return;
}
let tmp = this.numbers.splice(index, 1);
this.numbers.splice(newIndex, 0, tmp[0]);
}

// 向下滑
down(index: number): void {
if (!this.isDraggable(index + this.row)) {
return;
}
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
// 多列
this.itemMove(index, index + this.row);
}

// 向下滑(右下角为空)
down2(index: number): void {
if (!this.isDraggable(index + 3)) {
return;
}
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + 3);
}

// 向上滑
up(index: number): void {
if (!this.isDraggable(index - this.row)) {
return;
}
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - this.row);
}

// 向左滑
left(index: number): void {
if (!this.isDraggable(index - 1)) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.itemMove(index, index - 1);
}

// 向右滑
right(index: number): void {
if (!this.isDraggable(index + 1)) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.itemMove(index, index + 1);
}

// 向右下滑
lowerRight(index: number): void {
if (!this.isDraggable(index + this.row + 1)) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + this.row + 1);
}

// 向右上滑
upperRight(index: number): void {
if (!this.isDraggable(index - (this.row - 1))) {
return;
}
this.offsetX -= this.FIX_VP_X;
this.dragRefOffsetX += this.FIX_VP_X;
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - (this.row - 1));
}

// 向左下滑
lowerLeft(index: number): void {
if (!this.isDraggable(index + (this.row - 1))) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.offsetY -= this.FIX_VP_Y;
this.dragRefOffsetY += this.FIX_VP_Y;
this.itemMove(index, index + (this.row - 1));
}

// 向左上滑
upperLeft(index: number): void {
if (!this.isDraggable(index - (this.row + 1))) {
return;
}
this.offsetX += this.FIX_VP_X;
this.dragRefOffsetX -= this.FIX_VP_X;
this.offsetY += this.FIX_VP_Y;
this.dragRefOffsetY -= this.FIX_VP_Y;
this.itemMove(index, index - (this.row + 1));
}

// 通过元素的索引,控制对应元素是否能移动排序
isDraggable(index: number): boolean {
console.info(index: ${index});
return index > -1; // 恒成立,所有元素均可移动排序
}
https://pastebin.com/FQ7caXPg
https://pastebin.com/qrG8cLtE
https://pastebin.com/NDkKX7GA
https://pastebin.com/v7SbJUa2
https://pastebin.com/ckwh85Uv
https://pastebin.com/FyQiZnSa
https://pastebin.com/eJTdnrt3
https://pastebin.com/FSynV6Lb
https://pastebin.com/DAj2WRVR
https://pastebin.com/2Y0LWg8C
https://pastebin.com/U3rE0GN7
https://pastebin.com/5SqdHMZn
https://pastebin.com/3vZs9u6Y
https://pastebin.com/6SHV25A8
https://pastebin.com/cxcm4039
https://pastebin.com/Rgdfcp9d
https://pastebin.com/g8Thr4Mg
https://pastebin.com/rmwrNJji
https://pastebin.com/yKbAsYCa
https://pastebin.com/dRdM2X9u
https://pastebin.com/ecff1hqL
https://pastebin.com/UGKhTWQ8
https://pastebin.com/s5hexmMG
https://pastebin.com/vixNaxtq
https://pastebin.com/jM99sFyZ
https://pastebin.com/enua3UEF
https://pastebin.com/d0QccunL
https://pastebin.com/NW6ahtVi
https://pastebin.com/HdFmVJDd
https://pastebin.com/dvqz627c
https://pastebin.com/2dkeMADC
https://pastebin.com/H61nZMVs
https://pastebin.com/VAJYkWis
https://pastebin.com/3Y7xVCzF
https://pastebin.com/XWH0bcEB
https://pastebin.com/0yZbjU38
https://pastebin.com/KT9GU4Xj
https://pastebin.com/6JyqmT7e
https://pastebin.com/3fFG8u4J
https://pastebin.com/jLbepB1x
https://pastebin.com/fcqxvaXX
https://pastebin.com/3yKQCFzT
https://pastebin.com/Gpz5Yc8A
https://pastebin.com/KUjNqvfq
https://pastebin.com/JRp0SxQ5
https://pastebin.com/dAeJ7KxQ
https://pastebin.com/Y59qi6iT
https://pastebin.com/hsBpJYrt
https://pastebin.com/2wNNccE8
https://pastebin.com/dHCqmGeK
https://pastebin.com/5zYAQpvu
https://pastebin.com/dN3bshkc
https://pastebin.com/cFSUYDNN
https://pastebin.com/yWKUSPZz
https://pastebin.com/pjyMPVgp
https://pastebin.com/iASRBbGz
https://pastebin.com/zrVfHyC0
https://pastebin.com/Lg6i3qBs
https://pastebin.com/C9y6bEfC
https://pastebin.com/3xhPr5Uz
https://pastebin.com/u6fHcaUM
https://pastebin.com/GTjsW1uh
https://pastebin.com/15xfuW7r
https://pastebin.com/ATU9sQ6v
https://pastebin.com/a2mCY3Zz
https://pastebin.com/ntnWiFcr
https://pastebin.com/AH45r30t
https://pastebin.com/H0AQ1Dww
https://pastebin.com/diHn40ki
https://pastebin.com/CZH3ckGE
https://pastebin.com/UxAfGRQt
https://pastebin.com/FLNsUiG0
https://pastebin.com/AAWktRKj
https://pastebin.com/sKm7XvTE
https://pastebin.com/gvp4Q7sh
https://pastebin.com/xuCUMBur
https://pastebin.com/2espHLP1
https://pastebin.com/64pjxFAc
https://pastebin.com/J5fQPN5U
https://pastebin.com/J0rJg6DX
https://pastebin.com/QtWnkBDp
https://pastebin.com/SeGa4TkD
https://pastebin.com/WTwjcNN1
https://pastebin.com/MAqkmJXT
https://pastebin.com/sct8XVCM
https://pastebin.com/hkT7CqNH
https://pastebin.com/f7pCY395
https://pastebin.com/ZSbSpbL6
https://pastebin.com/Ug0RKLfK
https://pastebin.com/CV8Ercz3
https://pastebin.com/guYntd9W
https://pastebin.com/Dz3vpsZz
https://pastebin.com/0QCcxGWy
https://pastebin.com/Nd37dhtk
https://pastebin.com/yf59y43d
https://pastebin.com/nj7W9tyx
https://pastebin.com/5JCZtmRJ
https://pastebin.com/wagqVUtS
https://pastebin.com/1X65Yjc3
https://pastebin.com/TtXircBz
https://pastebin.com/fTwWHfEe
https://pastebin.com/zYrag51J
https://pastebin.com/E9icvGyK
https://pastebin.com/2cXwRAxL
https://pastebin.com/w0GGQRhc
https://pastebin.com/53sfuRZK
https://pastebin.com/90uQ7V15
https://pastebin.com/ghzaUYMF
https://pastebin.com/Nnpgvdes
https://pastebin.com/Y8tuCtaz
https://pastebin.com/iWx1huat
https://pastebin.com/FdQgitkv
https://pastebin.com/8amig0td
https://pastebin.com/yzcTvFfu
https://pastebin.com/68HwXpv5
https://pastebin.com/KLAWLeKM
https://pastebin.com/dMUbkzF2
https://pastebin.com/g6rLz6au
https://pastebin.com/trd44WK2
https://pastebin.com/cQ8audPK
https://pastebin.com/wRuQcX47
https://pastebin.com/nyzk75PP
https://pastebin.com/a52FLwqg
https://pastebin.com/ifwAEKs8
https://pastebin.com/7hsBC6eM
https://pastebin.com/pLAWFQ8U
https://pastebin.com/j70c8uBX
https://pastebin.com/ymKQsh4f
https://pastebin.com/4dqNaX6T
https://pastebin.com/HSdANUrQ
https://pastebin.com/Nh8sivuq
https://pastebin.com/q55w0w2i
https://pastebin.com/wXf37h3E
https://pastebin.com/RhAxX63P
https://pastebin.com/
https://pastebin.com/d0ftXeii
https://pastebin.com/w7cKXeMc
https://pastebin.com/vJQZ8zzg
https://pastebin.com/NV6uSXAB
https://pastebin.com/aDZckQqR
https://pastebin.com/LECR3S3x
https://pastebin.com/cp78R0ry
https://pastebin.com/WD0P7hDC
https://pastebin.com/iA0h7MsB
https://pastebin.com/509YHhv2
https://pastebin.com/sR22DfaA
https://pastebin.com/fkwWBgB1
https://pastebin.com/xu1tZaib
https://pastebin.com/0e9mbjm1
https://pastebin.com/8ygNAi7Q
https://pastebin.com/q10N4BVV
https://pastebin.com/E5a1VSUL
https://pastebin.com/N4rt7xkq
https://pastebin.com/KLKahxYp
https://pastebin.com/aAhka9TS
https://pastebin.com/cFzzqVdL
https://pastebin.com/TdF2uE9H
https://pastebin.com/sAwMjAbi
https://pastebin.com/DZNFtzZq
https://pastebin.com/tHjy4Dqz
https://pastebin.com/7nGK9sVT
https://pastebin.com/uh2XxG80
https://pastebin.com/AnR5ZVHR
https://pastebin.com/Y3RLNXTu
https://pastebin.com/H1QvABLE
https://pastebin.com/gu3H4ZCC
https://pastebin.com/6stL1Xpp
https://pastebin.com/yx5inydp
https://pastebin.com/hyiiCV2A
https://pastebin.com/rgCkSxnQ
https://pastebin.com/smR119Kz
https://pastebin.com/H6GguYti
https://pastebin.com/zMupz2e0
https://pastebin.com/hA0jPvEB
https://pastebin.com/a617mt5H
https://pastebin.com/nkjG08Fw
https://pastebin.com/k6NKap1G
https://pastebin.com/mmiNsmtC
https://pastebin.com/i6V5V5dz
https://pastebin.com/GUvCDwNE
https://pastebin.com/Cd7LEAAE
https://pastebin.com/uN4xeDXm
https://pastebin.com/WT2yyehE
https://pastebin.com/3qxa54xX
https://pastebin.com/xdnPSK9i
https://pastebin.com/EEpWrErg
https://pastebin.com/MbUH0ZVm
https://pastebin.com/UfRH2vMY
https://pastebin.com/qcmM4qiM
https://pastebin.com/0NXAxPQR
https://pastebin.com/bXmTJhyf
https://pastebin.com/716Zr85T
https://pastebin.com/X0JFDTJ0
https://pastebin.com/gSc7vpdF
https://pastebin.com/LKUU1kbW
https://pastebin.com/XfbRxeZ7
https://pastebin.com/afMDqP8e
https://pastebin.com/QxJgJX0x
https://pastebin.com/WGrQcNAF
https://pastebin.com/Kbj0zKmQ

收起阅读 »

如何解决NavDestination切换页面后浏览位置无法保存问题

问题现象
在HarmonyOS中,使用NavDestination实现页面跳转至其他页面后,下次进入如何保持跳转前页面的浏览位置?

背景知识
Navigation:Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(NavDestination的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
@ohos.arkui.observer(无感监听)提供UI组件行为变化的无感监听能力。可以监听Navigation的页面切换事件进行相应操作。
Scroll是一种可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
onDidScroll方法在Scroll滚动时触发,可用于在滑动过程中获取Scroll组件的偏移量yOffset。
scrollTo方法可用于让Scroll组件滑动到指定位置。
AppStorage是应用全局的UI状态存储,和应用的进程绑定,只能在UI主线程中使用,无法在子线程中使用、修改。
解决方案
方案一:使用路由模式保留页面实例。
在页面跳转时不要使用pop和clear等方法,否则NavDestination页面会被回收。可以采用单例模式MOVE_TO_TOP_SINGLETON跳转至指定的页面,该方式会使用栈内已存在的页面实例(即浏览位置不变)。

由于单例模式是从栈底到栈顶依次查找,当栈内存在多个同名页面实例时,会默认跳转最底层的同名页面实例,所以需确保栈内只存在一个同名实例,否则跳转的页面保留的滚动位置与上一次显示的页面会不一致(显示的是栈底同名实例保留的滚动位置)。
https://pastebin.com/Kvfw56Ui
https://pastebin.com/6Jk0iJHg
https://pastebin.com/aHSWm99J
https://pastebin.com/FgCAfbE3
https://pastebin.com/TdJAtZuS
https://pastebin.com/t5prk0xM
https://pastebin.com/9KBv8p6Z
https://pastebin.com/QzHRmSST
https://pastebin.com/EYerCiYE
https://pastebin.com/KQYtdiVR
https://pastebin.com/qPDGQpr7
https://pastebin.com/Ur2cbXAg
https://pastebin.com/niVM6VLk
https://pastebin.com/XpBnqUwS
https://pastebin.com/ndDMLQMC
https://pastebin.com/Fe0WC3pa
https://pastebin.com/RrnvPE1w
https://pastebin.com/bD5WPwRg
https://pastebin.com/YDh64vkT
https://pastebin.com/4LWHr9jc
https://pastebin.com/DCtRCCCk
https://pastebin.com/3p2Jzncu
https://pastebin.com/T3SJ62ar
https://pastebin.com/GKfL979H
https://pastebin.com/XMYGtPje
https://pastebin.com/rzXKvcuv
https://pastebin.com/JvR7cH5d
https://pastebin.com/3FDVEcuX
https://pastebin.com/h6cUiaBF
https://pastebin.com/ME4peSzL
https://pastebin.com/N5qAacXz
https://pastebin.com/JZZwHd6Z
https://pastebin.com/fGN6CmDR
https://pastebin.com/K3EVxehv
https://pastebin.com/PqCXWDDh
https://pastebin.com/fqusPVdu
https://pastebin.com/Dvt50mhL
https://pastebin.com/CtGAWTga
https://pastebin.com/XyuX26ci
https://pastebin.com/d9K2WJJt
https://pastebin.com/GwHXXvtC
https://pastebin.com/DDCwB3nj
https://pastebin.com/w0SKXPMz
https://pastebin.com/pN4H6zQh
https://pastebin.com/2MEDMTDa
https://pastebin.com/Km8YREQ6
https://pastebin.com/JCDkV4YW
https://pastebin.com/DVzuaCcx
https://pastebin.com/uc5iwWuj
https://pastebin.com/gNCWP8Qc
https://pastebin.com/Yu8Egw5s
https://pastebin.com/0LyQQjKP
https://pastebin.com/w5KFZYZd
https://pastebin.com/675wTRDu
https://pastebin.com/q3HydkUg
https://pastebin.com/zw5u9Qdi
https://pastebin.com/mzFWd75m
https://pastebin.com/xa0XPcNr
https://pastebin.com/YTTmLc1J
https://pastebin.com/81JwSJWW
https://pastebin.com/JZ5Yd8mP
https://pastebin.com/HYPHRp3p
https://pastebin.com/i7UKj8g6
https://pastebin.com/eS8TWDJF
https://pastebin.com/s17FvZ9R
https://pastebin.com/YG3qffNc
https://pastebin.com/Jm6jQ9Hr
https://pastebin.com/RyYPmYMa
https://pastebin.com/rtcK0Z53
https://pastebin.com/GX1W9zHA
https://pastebin.com/MydzWJwB
https://pastebin.com/sfxsFT66
https://pastebin.com/aayDqQsH
https://pastebin.com/GHia1M2L
https://pastebin.com/tHvSWiGS
https://pastebin.com/cJmt5rpy
https://pastebin.com/JYDkdGLs
https://pastebin.com/stRVBXTH
https://pastebin.com/G8gY33rM
https://pastebin.com/yWTE4s8z
https://pastebin.com/bF237U4E
https://pastebin.com/A2XjbJFL
https://pastebin.com/CMPsmXHW
https://pastebin.com/XBnbf5yR
https://pastebin.com/2WTSxuZH
https://pastebin.com/x9TYHnnR
https://pastebin.com/yr442rZ9
https://pastebin.com/kTQXdYBq
https://pastebin.com/sXG2mktr
https://pastebin.com/sHKZkR2S
https://pastebin.com/VgaMNyjP
https://pastebin.com/saBuBbfx
https://pastebin.com/Akn339vN
https://pastebin.com/LxJpgWdH
https://pastebin.com/gCUJtG1r
https://pastebin.com/bNS4mhKg
https://pastebin.com/PKcfHFsC
https://pastebin.com/3cMHb88V
https://pastebin.com/3HyqCceQ
https://pastebin.com/NpPEKWNc
https://pastebin.com/Mxr4rfx3
https://pastebin.com/1ND8zgqs
https://pastebin.com/Bk8zT2RD
https://pastebin.com/PivBT23m
https://pastebin.com/PhBTFTus
https://pastebin.com/iRW432jR
https://pastebin.com/W4Euyfpd
https://pastebin.com/E9JLP4M1
https://pastebin.com/2G53rfER
https://pastebin.com/GCiDaiZh
https://pastebin.com/jd9TTX9d
https://pastebin.com/Ah3LCi7e
https://pastebin.com/mNF9WeS7
https://pastebin.com/aKzY3GUc
https://pastebin.com/n7cevaYk
https://pastebin.com/GDDDzUuy
https://pastebin.com/tyx4arNi
https://pastebin.com/j54FMwvB
https://pastebin.com/2cRztMQY
https://pastebin.com/G6WWzmMF
https://pastebin.com/eVszwUfs
https://pastebin.com/D4rYGpE6
https://pastebin.com/6Jya9VEL
https://pastebin.com/vyFWsBCr
https://pastebin.com/pv7BP9vr
https://pastebin.com/RhR9FeUP
https://pastebin.com/vWxFY2YW
https://pastebin.com/Lairj5Ld
https://pastebin.com/jwQKSavR
https://pastebin.com/8GvaRTz1
https://pastebin.com/3YHX2qmE
https://pastebin.com/kssYcnr7
https://pastebin.com/NtnKhtYY
https://pastebin.com/Fz6cc5Le
https://pastebin.com/icc6WRsj
https://pastebin.com/wWk9nFRp
https://pastebin.com/eXQgBJMX
https://pastebin.com/z0xrXUZ3
https://pastebin.com/spSBiP8J
https://pastebin.com/AaUJmpHM
https://pastebin.com/3x1w4uHd
https://pastebin.com/pKZvNg7m
https://pastebin.com/Qb6vxDTQ
https://pastebin.com/P0S6wfBk
https://pastebin.com/444CJvwY
https://pastebin.com/7MkiVbks
https://pastebin.com/45wrx7jX
https://pastebin.com/J6M4Hh9S
https://pastebin.com/T5gQ6kJV
https://pastebin.com/h4K76YnL
https://pastebin.com/Kmx8rkB5
https://pastebin.com/42F7A6X9
https://pastebin.com/qnTdJLyj
https://pastebin.com/LTBywbqr
https://pastebin.com/2sQhNdXp
https://pastebin.com/mhSnZhNt
https://pastebin.com/wEfqig2G
https://pastebin.com/HbyYyFs0
https://pastebin.com/vUXzYbcc
https://pastebin.com/nDJnT1yM
https://pastebin.com/DKM75CX4
https://pastebin.com/hB0980pZ
https://pastebin.com/Nk6s4uGj
https://pastebin.com/PJf3D7tg
https://pastebin.com/5Sr8y30c
https://pastebin.com/huf9nsJ4
https://pastebin.com/xtBzF05M
https://pastebin.com/JFmF4u1f
https://pastebin.com/4zmGeM48
https://pastebin.com/UB9TNyxW
https://pastebin.com/cXSRyukE
https://pastebin.com/XdhcwfBp
https://pastebin.com/UYMVPFgN
https://pastebin.com/c62H8NxQ
https://pastebin.com/84DXZjfQ
https://pastebin.com/fFepWW4H
https://pastebin.com/3Sq1TF6k
https://pastebin.com/SQPTntKg
https://pastebin.com/khc1nD0w
https://pastebin.com/p8beJJva
https://pastebin.com/9LfnVJAJ
https://pastebin.com/M6QchRZ9
https://pastebin.com/Egxy8RxR
https://pastebin.com/D9v72rK6
https://pastebin.com/82dq2ZHB
https://pastebin.com/WtWcMEAa
https://pastebin.com/FhzkMMw1
https://pastebin.com/s5kf22wS
https://pastebin.com/kxXm99HH
https://pastebin.com/ZeUdrbC7
https://pastebin.com/Uyd0wkV5
https://pastebin.com/Gj32PSKS
https://pastebin.com/QWZZkFKR
https://pastebin.com/Hd2BgPS5
https://pastebin.com/hdiUJFS0
https://pastebin.com/u2Gt9cfq
https://pastebin.com/0vHYKc8F
https://pastebin.com/TZVHGvLR
https://pastebin.com/VFxecajq
https://pastebin.com/nWj4HsBJ
https://pastebin.com/G8GUM8fz
https://pastebin.com/LReXd1m0
https://pastebin.com/fpQnrYTL
https://pastebin.com/RyDHm8nK
https://pastebin.com/4gAzEceK
https://pastebin.com/AgGD7Sw8
https://pastebin.com/Zh7srRfN
https://pastebin.com/2y9BHBvR
https://pastebin.com/cZ9yHWab
https://pastebin.com/NRHZcAUe
https://pastebin.com/qfC6uqGY
https://pastebin.com/pzbatnT2
https://pastebin.com/pytQrM3n
https://pastebin.com/zv1bEjfh
https://pastebin.com/Z7CHKjjW
https://pastebin.com/73NZB1fg
https://pastebin.com/zb96CYYT
https://pastebin.com/TVSbCuk0
https://pastebin.com/PQH1YKrR
https://pastebin.com/bv5qqT8j
https://pastebin.com/WpenkS9J
https://pastebin.com/jkgzXhCX
https://pastebin.com/pT7xkBGP
https://pastebin.com/ppyQuy1c
https://pastebin.com/LdT3rmMu
https://pastebin.com/EVTt0G5t
https://pastebin.com/Lv4a1muV
https://pastebin.com/zmTAWL2U
https://pastebin.com/QdxecLbK
https://pastebin.com/3kZ5NwrU
https://pastebin.com/TPJsBatd
https://pastebin.com/WfhnNpFV
https://pastebin.com/SAmdt79t
https://pastebin.com/JZ4KvEWL
https://pastebin.com/uGcyWALB
https://pastebin.com/MEq4JbqR
https://pastebin.com/3ucqcbc6
https://pastebin.com/3cDtaAwF
https://pastebin.com/yzn2GGYf
https://pastebin.com/RTjPyJNX
https://pastebin.com/SQDC9M1E
https://pastebin.com/xcasG7xf
https://pastebin.com/zZfPyQY3
https://pastebin.com/RNzWpA4q
https://pastebin.com/8pufepjf
https://pastebin.com/vxDSuXem
https://pastebin.com/HP4y0h1f
https://pastebin.com/46jYNt7j
https://pastebin.com/YUvcKeAw
https://pastebin.com/wGfKDBZe
https://pastebin.com/bccZqgn7
https://pastebin.com/cBisnNN3
https://pastebin.com/4WFqkrmi
https://pastebin.com/fc7jp78E
https://pastebin.com/yjptCxY9
https://pastebin.com/2D6R3N5s
https://pastebin.com/KvR4cDki
https://pastebin.com/Vk1Rk7uj
https://pastebin.com/JEiNNYpi
https://pastebin.com/PyzV38G0
https://pastebin.com/KbzwD20r
https://pastebin.com/ViKS1JgQ
https://pastebin.com/5YcYwqDE
https://pastebin.com/ZFMU4ndk
https://pastebin.com/0Ex2wTma
https://pastebin.com/pQ7MD6DZ
https://pastebin.com/UCTHHnqH
https://pastebin.com/sDEyLgsy
https://pastebin.com/Z7Wrv3qq
https://pastebin.com/qb5YncFh
https://pastebin.com/uibzH23E
https://pastebin.com/4ykQaXqk
https://pastebin.com/K5mKVf1G
https://pastebin.com/xYEugHiP
https://pastebin.com/z8JzmxYY
https://pastebin.com/0UXR57Di
https://pastebin.com/0hmA61Hd
https://pastebin.com/tPkKjDC1
https://pastebin.com/v0ra9Mya
https://pastebin.com/puHjxuHP
https://pastebin.com/fYS5Dnw5
https://pastebin.com/xDwmcBVp
https://pastebin.com/vYi6rTmN

继续阅读 »

问题现象
在HarmonyOS中,使用NavDestination实现页面跳转至其他页面后,下次进入如何保持跳转前页面的浏览位置?

背景知识
Navigation:Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(NavDestination的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
@ohos.arkui.observer(无感监听)提供UI组件行为变化的无感监听能力。可以监听Navigation的页面切换事件进行相应操作。
Scroll是一种可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
onDidScroll方法在Scroll滚动时触发,可用于在滑动过程中获取Scroll组件的偏移量yOffset。
scrollTo方法可用于让Scroll组件滑动到指定位置。
AppStorage是应用全局的UI状态存储,和应用的进程绑定,只能在UI主线程中使用,无法在子线程中使用、修改。
解决方案
方案一:使用路由模式保留页面实例。
在页面跳转时不要使用pop和clear等方法,否则NavDestination页面会被回收。可以采用单例模式MOVE_TO_TOP_SINGLETON跳转至指定的页面,该方式会使用栈内已存在的页面实例(即浏览位置不变)。

由于单例模式是从栈底到栈顶依次查找,当栈内存在多个同名页面实例时,会默认跳转最底层的同名页面实例,所以需确保栈内只存在一个同名实例,否则跳转的页面保留的滚动位置与上一次显示的页面会不一致(显示的是栈底同名实例保留的滚动位置)。
https://pastebin.com/Kvfw56Ui
https://pastebin.com/6Jk0iJHg
https://pastebin.com/aHSWm99J
https://pastebin.com/FgCAfbE3
https://pastebin.com/TdJAtZuS
https://pastebin.com/t5prk0xM
https://pastebin.com/9KBv8p6Z
https://pastebin.com/QzHRmSST
https://pastebin.com/EYerCiYE
https://pastebin.com/KQYtdiVR
https://pastebin.com/qPDGQpr7
https://pastebin.com/Ur2cbXAg
https://pastebin.com/niVM6VLk
https://pastebin.com/XpBnqUwS
https://pastebin.com/ndDMLQMC
https://pastebin.com/Fe0WC3pa
https://pastebin.com/RrnvPE1w
https://pastebin.com/bD5WPwRg
https://pastebin.com/YDh64vkT
https://pastebin.com/4LWHr9jc
https://pastebin.com/DCtRCCCk
https://pastebin.com/3p2Jzncu
https://pastebin.com/T3SJ62ar
https://pastebin.com/GKfL979H
https://pastebin.com/XMYGtPje
https://pastebin.com/rzXKvcuv
https://pastebin.com/JvR7cH5d
https://pastebin.com/3FDVEcuX
https://pastebin.com/h6cUiaBF
https://pastebin.com/ME4peSzL
https://pastebin.com/N5qAacXz
https://pastebin.com/JZZwHd6Z
https://pastebin.com/fGN6CmDR
https://pastebin.com/K3EVxehv
https://pastebin.com/PqCXWDDh
https://pastebin.com/fqusPVdu
https://pastebin.com/Dvt50mhL
https://pastebin.com/CtGAWTga
https://pastebin.com/XyuX26ci
https://pastebin.com/d9K2WJJt
https://pastebin.com/GwHXXvtC
https://pastebin.com/DDCwB3nj
https://pastebin.com/w0SKXPMz
https://pastebin.com/pN4H6zQh
https://pastebin.com/2MEDMTDa
https://pastebin.com/Km8YREQ6
https://pastebin.com/JCDkV4YW
https://pastebin.com/DVzuaCcx
https://pastebin.com/uc5iwWuj
https://pastebin.com/gNCWP8Qc
https://pastebin.com/Yu8Egw5s
https://pastebin.com/0LyQQjKP
https://pastebin.com/w5KFZYZd
https://pastebin.com/675wTRDu
https://pastebin.com/q3HydkUg
https://pastebin.com/zw5u9Qdi
https://pastebin.com/mzFWd75m
https://pastebin.com/xa0XPcNr
https://pastebin.com/YTTmLc1J
https://pastebin.com/81JwSJWW
https://pastebin.com/JZ5Yd8mP
https://pastebin.com/HYPHRp3p
https://pastebin.com/i7UKj8g6
https://pastebin.com/eS8TWDJF
https://pastebin.com/s17FvZ9R
https://pastebin.com/YG3qffNc
https://pastebin.com/Jm6jQ9Hr
https://pastebin.com/RyYPmYMa
https://pastebin.com/rtcK0Z53
https://pastebin.com/GX1W9zHA
https://pastebin.com/MydzWJwB
https://pastebin.com/sfxsFT66
https://pastebin.com/aayDqQsH
https://pastebin.com/GHia1M2L
https://pastebin.com/tHvSWiGS
https://pastebin.com/cJmt5rpy
https://pastebin.com/JYDkdGLs
https://pastebin.com/stRVBXTH
https://pastebin.com/G8gY33rM
https://pastebin.com/yWTE4s8z
https://pastebin.com/bF237U4E
https://pastebin.com/A2XjbJFL
https://pastebin.com/CMPsmXHW
https://pastebin.com/XBnbf5yR
https://pastebin.com/2WTSxuZH
https://pastebin.com/x9TYHnnR
https://pastebin.com/yr442rZ9
https://pastebin.com/kTQXdYBq
https://pastebin.com/sXG2mktr
https://pastebin.com/sHKZkR2S
https://pastebin.com/VgaMNyjP
https://pastebin.com/saBuBbfx
https://pastebin.com/Akn339vN
https://pastebin.com/LxJpgWdH
https://pastebin.com/gCUJtG1r
https://pastebin.com/bNS4mhKg
https://pastebin.com/PKcfHFsC
https://pastebin.com/3cMHb88V
https://pastebin.com/3HyqCceQ
https://pastebin.com/NpPEKWNc
https://pastebin.com/Mxr4rfx3
https://pastebin.com/1ND8zgqs
https://pastebin.com/Bk8zT2RD
https://pastebin.com/PivBT23m
https://pastebin.com/PhBTFTus
https://pastebin.com/iRW432jR
https://pastebin.com/W4Euyfpd
https://pastebin.com/E9JLP4M1
https://pastebin.com/2G53rfER
https://pastebin.com/GCiDaiZh
https://pastebin.com/jd9TTX9d
https://pastebin.com/Ah3LCi7e
https://pastebin.com/mNF9WeS7
https://pastebin.com/aKzY3GUc
https://pastebin.com/n7cevaYk
https://pastebin.com/GDDDzUuy
https://pastebin.com/tyx4arNi
https://pastebin.com/j54FMwvB
https://pastebin.com/2cRztMQY
https://pastebin.com/G6WWzmMF
https://pastebin.com/eVszwUfs
https://pastebin.com/D4rYGpE6
https://pastebin.com/6Jya9VEL
https://pastebin.com/vyFWsBCr
https://pastebin.com/pv7BP9vr
https://pastebin.com/RhR9FeUP
https://pastebin.com/vWxFY2YW
https://pastebin.com/Lairj5Ld
https://pastebin.com/jwQKSavR
https://pastebin.com/8GvaRTz1
https://pastebin.com/3YHX2qmE
https://pastebin.com/kssYcnr7
https://pastebin.com/NtnKhtYY
https://pastebin.com/Fz6cc5Le
https://pastebin.com/icc6WRsj
https://pastebin.com/wWk9nFRp
https://pastebin.com/eXQgBJMX
https://pastebin.com/z0xrXUZ3
https://pastebin.com/spSBiP8J
https://pastebin.com/AaUJmpHM
https://pastebin.com/3x1w4uHd
https://pastebin.com/pKZvNg7m
https://pastebin.com/Qb6vxDTQ
https://pastebin.com/P0S6wfBk
https://pastebin.com/444CJvwY
https://pastebin.com/7MkiVbks
https://pastebin.com/45wrx7jX
https://pastebin.com/J6M4Hh9S
https://pastebin.com/T5gQ6kJV
https://pastebin.com/h4K76YnL
https://pastebin.com/Kmx8rkB5
https://pastebin.com/42F7A6X9
https://pastebin.com/qnTdJLyj
https://pastebin.com/LTBywbqr
https://pastebin.com/2sQhNdXp
https://pastebin.com/mhSnZhNt
https://pastebin.com/wEfqig2G
https://pastebin.com/HbyYyFs0
https://pastebin.com/vUXzYbcc
https://pastebin.com/nDJnT1yM
https://pastebin.com/DKM75CX4
https://pastebin.com/hB0980pZ
https://pastebin.com/Nk6s4uGj
https://pastebin.com/PJf3D7tg
https://pastebin.com/5Sr8y30c
https://pastebin.com/huf9nsJ4
https://pastebin.com/xtBzF05M
https://pastebin.com/JFmF4u1f
https://pastebin.com/4zmGeM48
https://pastebin.com/UB9TNyxW
https://pastebin.com/cXSRyukE
https://pastebin.com/XdhcwfBp
https://pastebin.com/UYMVPFgN
https://pastebin.com/c62H8NxQ
https://pastebin.com/84DXZjfQ
https://pastebin.com/fFepWW4H
https://pastebin.com/3Sq1TF6k
https://pastebin.com/SQPTntKg
https://pastebin.com/khc1nD0w
https://pastebin.com/p8beJJva
https://pastebin.com/9LfnVJAJ
https://pastebin.com/M6QchRZ9
https://pastebin.com/Egxy8RxR
https://pastebin.com/D9v72rK6
https://pastebin.com/82dq2ZHB
https://pastebin.com/WtWcMEAa
https://pastebin.com/FhzkMMw1
https://pastebin.com/s5kf22wS
https://pastebin.com/kxXm99HH
https://pastebin.com/ZeUdrbC7
https://pastebin.com/Uyd0wkV5
https://pastebin.com/Gj32PSKS
https://pastebin.com/QWZZkFKR
https://pastebin.com/Hd2BgPS5
https://pastebin.com/hdiUJFS0
https://pastebin.com/u2Gt9cfq
https://pastebin.com/0vHYKc8F
https://pastebin.com/TZVHGvLR
https://pastebin.com/VFxecajq
https://pastebin.com/nWj4HsBJ
https://pastebin.com/G8GUM8fz
https://pastebin.com/LReXd1m0
https://pastebin.com/fpQnrYTL
https://pastebin.com/RyDHm8nK
https://pastebin.com/4gAzEceK
https://pastebin.com/AgGD7Sw8
https://pastebin.com/Zh7srRfN
https://pastebin.com/2y9BHBvR
https://pastebin.com/cZ9yHWab
https://pastebin.com/NRHZcAUe
https://pastebin.com/qfC6uqGY
https://pastebin.com/pzbatnT2
https://pastebin.com/pytQrM3n
https://pastebin.com/zv1bEjfh
https://pastebin.com/Z7CHKjjW
https://pastebin.com/73NZB1fg
https://pastebin.com/zb96CYYT
https://pastebin.com/TVSbCuk0
https://pastebin.com/PQH1YKrR
https://pastebin.com/bv5qqT8j
https://pastebin.com/WpenkS9J
https://pastebin.com/jkgzXhCX
https://pastebin.com/pT7xkBGP
https://pastebin.com/ppyQuy1c
https://pastebin.com/LdT3rmMu
https://pastebin.com/EVTt0G5t
https://pastebin.com/Lv4a1muV
https://pastebin.com/zmTAWL2U
https://pastebin.com/QdxecLbK
https://pastebin.com/3kZ5NwrU
https://pastebin.com/TPJsBatd
https://pastebin.com/WfhnNpFV
https://pastebin.com/SAmdt79t
https://pastebin.com/JZ4KvEWL
https://pastebin.com/uGcyWALB
https://pastebin.com/MEq4JbqR
https://pastebin.com/3ucqcbc6
https://pastebin.com/3cDtaAwF
https://pastebin.com/yzn2GGYf
https://pastebin.com/RTjPyJNX
https://pastebin.com/SQDC9M1E
https://pastebin.com/xcasG7xf
https://pastebin.com/zZfPyQY3
https://pastebin.com/RNzWpA4q
https://pastebin.com/8pufepjf
https://pastebin.com/vxDSuXem
https://pastebin.com/HP4y0h1f
https://pastebin.com/46jYNt7j
https://pastebin.com/YUvcKeAw
https://pastebin.com/wGfKDBZe
https://pastebin.com/bccZqgn7
https://pastebin.com/cBisnNN3
https://pastebin.com/4WFqkrmi
https://pastebin.com/fc7jp78E
https://pastebin.com/yjptCxY9
https://pastebin.com/2D6R3N5s
https://pastebin.com/KvR4cDki
https://pastebin.com/Vk1Rk7uj
https://pastebin.com/JEiNNYpi
https://pastebin.com/PyzV38G0
https://pastebin.com/KbzwD20r
https://pastebin.com/ViKS1JgQ
https://pastebin.com/5YcYwqDE
https://pastebin.com/ZFMU4ndk
https://pastebin.com/0Ex2wTma
https://pastebin.com/pQ7MD6DZ
https://pastebin.com/UCTHHnqH
https://pastebin.com/sDEyLgsy
https://pastebin.com/Z7Wrv3qq
https://pastebin.com/qb5YncFh
https://pastebin.com/uibzH23E
https://pastebin.com/4ykQaXqk
https://pastebin.com/K5mKVf1G
https://pastebin.com/xYEugHiP
https://pastebin.com/z8JzmxYY
https://pastebin.com/0UXR57Di
https://pastebin.com/0hmA61Hd
https://pastebin.com/tPkKjDC1
https://pastebin.com/v0ra9Mya
https://pastebin.com/puHjxuHP
https://pastebin.com/fYS5Dnw5
https://pastebin.com/xDwmcBVp
https://pastebin.com/vYi6rTmN

收起阅读 »

发布ipa文件到开发者中心的最简方法

上架

假如是使用mac电脑,可以使用xcode上传。也可以使用xcode的命令行工具来上传,

但是windows电脑没有xcode这些工具,也没有windows版本的xcode。不过安装xcode比较大,也比较麻烦,mac电脑假如没空间,也可以使用下面windows的方法来上传。

windows电脑发布ipa文件到苹果开发者中心的构建版本,就不能使用xcode,windows发布ipa到构建版本,可使用香蕉云编来上传。

下面,是windows电脑上传ipa的方法:
(1)打开香蕉云编,进入后台,使用上传ipa到app store的功能,点击上传新文件

(2)进入密钥或密码填写界面

这里可以使用app store密钥上传或者专用密码上传,这里建议使用app store密钥上传,更加专业和可靠,因为密钥永远不会失效。

(3)设置app store密钥
假如是第一次上传,还没有app store密钥,就需要先去app store先设置密钥,上传界面有设计密钥或专用密码的教程。

(4)上传ipa
填写完所有资料,最后一步,就是上传ipa了,上传过程大概一两分钟,就可以看到上传成功了。上传成功半小时后,留意苹果的邮件,看看有没有成功进入构建版本。

继续阅读 »

假如是使用mac电脑,可以使用xcode上传。也可以使用xcode的命令行工具来上传,

但是windows电脑没有xcode这些工具,也没有windows版本的xcode。不过安装xcode比较大,也比较麻烦,mac电脑假如没空间,也可以使用下面windows的方法来上传。

windows电脑发布ipa文件到苹果开发者中心的构建版本,就不能使用xcode,windows发布ipa到构建版本,可使用香蕉云编来上传。

下面,是windows电脑上传ipa的方法:
(1)打开香蕉云编,进入后台,使用上传ipa到app store的功能,点击上传新文件

(2)进入密钥或密码填写界面

这里可以使用app store密钥上传或者专用密码上传,这里建议使用app store密钥上传,更加专业和可靠,因为密钥永远不会失效。

(3)设置app store密钥
假如是第一次上传,还没有app store密钥,就需要先去app store先设置密钥,上传界面有设计密钥或专用密码的教程。

(4)上传ipa
填写完所有资料,最后一步,就是上传ipa了,上传过程大概一两分钟,就可以看到上传成功了。上传成功半小时后,留意苹果的邮件,看看有没有成功进入构建版本。

收起阅读 »

windows上架ios app详细经验分享

应用上架

在hbuilderx打包ios应用,ios应用最终编译和打包后,会产生一个ipa格式的压缩文件,是一个.ipa后缀的文件。这个文件在苹果商店里叫构建版本。

上架的时候,需要将这个ipa文件上传到app store的构建版本上,需要使用第三方上传工具来上传。

跨平台工具:香蕉云编

mac电脑工具:xcode或者transporter

由于这里需要兼顾windows和linux开发者,因此,这个教程主要是针对使用香蕉云编上传的教程。

(一)进入苹果开发者中心后台

在苹果开发者中心,点击登录图标登录,登录后就进入苹果开发者中心的后台,可以看到app store connect这个板块,这个板块里面有个App菜单,如下图所示:

点击App这个菜单,进入APP列表页面。

(二)新建App

进入App列表页面后,假如App还不存在,则需要新新建一个App才能正式上架。
新建的时候后,需要填写名称、主要语言、套装ID和SKU这些信息,其中套装ID一定要选对,这个跟你打包的APP的appId是对应的:

(三)填写资料

点击App列表页面的App名称,就可以填写APP资料上架了。

(四)上传构建版本

在页面下面,有一项是需要选择构建版本,也就是上传ipa文件到这里。
但在苹果开发者中心无法直接上传ipa文件,因为它需要做一些ipa文件完整性校验。需要使用第三方工具来上传。这里可以使用跨平台的香蕉云编这个工具来上传:

https://www.yunedit.com/ipasend

(五)在香蕉云编上传ipa到构建版本

登录香蕉云编,进入上传ipa到app store的功能菜单,点击上传后,出现这个界面:

在上传界面里,可以使用app store密钥或者专用密码两种方法上传,这里推荐使用app store密钥上传,因为专用密码有时候会失效,比如改了用户登录密码后,专用密码也会失效。

app store密钥的设置方法,可以参考上图红色字体的教程。

(六)等待苹果邮件

在香蕉云编上传成功后,还不一定能上传到构建版本里面去,因为你的APP还可能有问题,需要等半个小时,再查看苹果邮件,看看有没有报错信息。

(七)上架

受到苹果邮件后,假如提示上传成功,就可以在刚才选择构建版本的界面,点蓝色加号选择构建版本了。

选择完构建版本,填写完其他的资料,就可以上架啦,上架要等待苹果人工审核。

继续阅读 »

在hbuilderx打包ios应用,ios应用最终编译和打包后,会产生一个ipa格式的压缩文件,是一个.ipa后缀的文件。这个文件在苹果商店里叫构建版本。

上架的时候,需要将这个ipa文件上传到app store的构建版本上,需要使用第三方上传工具来上传。

跨平台工具:香蕉云编

mac电脑工具:xcode或者transporter

由于这里需要兼顾windows和linux开发者,因此,这个教程主要是针对使用香蕉云编上传的教程。

(一)进入苹果开发者中心后台

在苹果开发者中心,点击登录图标登录,登录后就进入苹果开发者中心的后台,可以看到app store connect这个板块,这个板块里面有个App菜单,如下图所示:

点击App这个菜单,进入APP列表页面。

(二)新建App

进入App列表页面后,假如App还不存在,则需要新新建一个App才能正式上架。
新建的时候后,需要填写名称、主要语言、套装ID和SKU这些信息,其中套装ID一定要选对,这个跟你打包的APP的appId是对应的:

(三)填写资料

点击App列表页面的App名称,就可以填写APP资料上架了。

(四)上传构建版本

在页面下面,有一项是需要选择构建版本,也就是上传ipa文件到这里。
但在苹果开发者中心无法直接上传ipa文件,因为它需要做一些ipa文件完整性校验。需要使用第三方工具来上传。这里可以使用跨平台的香蕉云编这个工具来上传:

https://www.yunedit.com/ipasend

(五)在香蕉云编上传ipa到构建版本

登录香蕉云编,进入上传ipa到app store的功能菜单,点击上传后,出现这个界面:

在上传界面里,可以使用app store密钥或者专用密码两种方法上传,这里推荐使用app store密钥上传,因为专用密码有时候会失效,比如改了用户登录密码后,专用密码也会失效。

app store密钥的设置方法,可以参考上图红色字体的教程。

(六)等待苹果邮件

在香蕉云编上传成功后,还不一定能上传到构建版本里面去,因为你的APP还可能有问题,需要等半个小时,再查看苹果邮件,看看有没有报错信息。

(七)上架

受到苹果邮件后,假如提示上传成功,就可以在刚才选择构建版本的界面,点蓝色加号选择构建版本了。

选择完构建版本,填写完其他的资料,就可以上架啦,上架要等待苹果人工审核。

收起阅读 »

hbuilderx打包报证书过期,解决方案:使用香蕉云编重新生成

iOS证书

打包的时候,报遇到The certificate is expired这个错误,字面意思其实很明了,就是证书过期了。

管理证书的组好的方法,最好是亲自去苹果开发者开发者中心生成,这样可以充分了解ios证书过期的生命周期,也可以提前创建和管理证书,这里我推荐使用香蕉云编+苹果开发者中心来生成。

主要是在苹果开发者中心,删除旧的证书和profile文件,然后重新生成。

而因为在苹果开发者中心,生成证书的时候,由于需要提供csr这种文件,生成完证书后还需要导出成p12格式的私钥证书,因此需要香蕉云编作为辅助功能来做配合。工具:

https://www.yunedit.com/createcert

直接使用这个工具来生成即可,傻瓜式的可视化工具,假如流程有不懂,可以直接看工具里生成证书界面的教程。

继续阅读 »

打包的时候,报遇到The certificate is expired这个错误,字面意思其实很明了,就是证书过期了。

管理证书的组好的方法,最好是亲自去苹果开发者开发者中心生成,这样可以充分了解ios证书过期的生命周期,也可以提前创建和管理证书,这里我推荐使用香蕉云编+苹果开发者中心来生成。

主要是在苹果开发者中心,删除旧的证书和profile文件,然后重新生成。

而因为在苹果开发者中心,生成证书的时候,由于需要提供csr这种文件,生成完证书后还需要导出成p12格式的私钥证书,因此需要香蕉云编作为辅助功能来做配合。工具:

https://www.yunedit.com/createcert

直接使用这个工具来生成即可,傻瓜式的可视化工具,假如流程有不懂,可以直接看工具里生成证书界面的教程。

收起阅读 »

寻找有企业证书的小伙伴咨询洽谈,酬劳丰厚!

App打包 iOS打包 uni_app 上架

公司有项目需要上传,绝对正规且合规,需要跟由企业证书的小伙伴咨询一下相关事宜,酬劳丰厚(不低于几个月工资)!!qq290783040 .不用留言,请直接加我。万分感谢本平台能够提供交流的空间。

公司有项目需要上传,绝对正规且合规,需要跟由企业证书的小伙伴咨询一下相关事宜,酬劳丰厚(不低于几个月工资)!!qq290783040 .不用留言,请直接加我。万分感谢本平台能够提供交流的空间。

快速创建ios自有证书和profile文件的方法

iOS证书

在hbuilderx打包的时候,想放到发布平台去扫码测试,或者上架app store connect,需要使用自建证书打包,不能再使用数据线连接的方式安装到手机。

而创建ios证书的教程,提示我们需要使用mac电脑的钥匙串访问去申请证书,然而我的电脑却是windows电脑。

后来发现没有mac电脑能创建ios证书,可以使用香蕉云编来生成p12私钥证书,profile文件在苹果开发者中心就可以生成,不需要mac电脑。

创建的过程如下:

1)申请苹果开发账号,这个步骤最麻烦最消耗时间,可以参考下面的教程申请苹果开发账号。完成这步后,后面的步骤都很简单。假如你们公司已经有账号就不需要申请账号了。

https://juejin.cn/post/7529496810265575458

2)进入苹果开发者中心,点击证书功能,创建一个证书,创建证书的第一步,选择ios distribution类型的证书。

3) 创建证书的过程中,提示需要提供一个csr文件,提示需要在mac电脑申请这个文件。如下图所示:

4)这个步骤,可以不用mac电脑来申请,可以改用香蕉云编来代替:
https://www.yunedit.com/createcert

5)接着下一步,就生成证书文件了。在苹果开发者中心下载下来,证书是.cer后缀格式的,还不是hbuilderx所需的p12格式的证书。

6)接着使用香蕉云编,生成p12证书的功能,将cer转换成p12格式,生成p12证书前,是需要先上传刚才在苹果开发者中心生成的cer证书去香蕉云编先的,如下图所示:

完成上面6个步骤,p12私钥证书文件就创建完毕了。

还有profile文件需要创建。

7)登录苹果开发者中心,找到Identifiers模块,创建一个应用。
注意,创建应用的时候,填写的应用的APPID,需要填写一个java格式的包名,一般是com.xxname.xxapp这样的格式。
这个appId,是跟hbuilderx的云打包里面的包名对应的,需要一致。

8)创建profile文件,在苹果开发者中心,找到profile模块,就可以创建profile了。
在这里需要提醒的是,创建profile的时候,假如选择app store connect类型,就是创建上架类型的profile。
假如创建的是Ad hoc类型,就是真机测试类型,可以用来给团队其他成员安装测试的。生成ad hoc类型的话,可以放到香蕉云编或者蒲公英这种测试平台来扫码安装。

创建profile的过程还需要绑定APPID(应用)和绑定Certificate(证书)的,就是绑定前几个创建的应用和证书,假如你有多个应用或多个证书,可别选错了。

假如选择的是ad hoc类型,它提示还需要绑定测试设备的udid的,你还是提前获取到你团队的所有udid,再去创建测试类型的profile文件。因为添加了新成员,profile又需要重新创建的,重下下载profile文件的。

获取udid的最简单的方法是使用ios测试设备,扫描香蕉云编获取udid的工具,根据它的提示来获取udid:
https://www.yunedit.com/udid

好了,完成上面的8个步骤,证书和profile文件应该就创建完了。

继续阅读 »

在hbuilderx打包的时候,想放到发布平台去扫码测试,或者上架app store connect,需要使用自建证书打包,不能再使用数据线连接的方式安装到手机。

而创建ios证书的教程,提示我们需要使用mac电脑的钥匙串访问去申请证书,然而我的电脑却是windows电脑。

后来发现没有mac电脑能创建ios证书,可以使用香蕉云编来生成p12私钥证书,profile文件在苹果开发者中心就可以生成,不需要mac电脑。

创建的过程如下:

1)申请苹果开发账号,这个步骤最麻烦最消耗时间,可以参考下面的教程申请苹果开发账号。完成这步后,后面的步骤都很简单。假如你们公司已经有账号就不需要申请账号了。

https://juejin.cn/post/7529496810265575458

2)进入苹果开发者中心,点击证书功能,创建一个证书,创建证书的第一步,选择ios distribution类型的证书。

3) 创建证书的过程中,提示需要提供一个csr文件,提示需要在mac电脑申请这个文件。如下图所示:

4)这个步骤,可以不用mac电脑来申请,可以改用香蕉云编来代替:
https://www.yunedit.com/createcert

5)接着下一步,就生成证书文件了。在苹果开发者中心下载下来,证书是.cer后缀格式的,还不是hbuilderx所需的p12格式的证书。

6)接着使用香蕉云编,生成p12证书的功能,将cer转换成p12格式,生成p12证书前,是需要先上传刚才在苹果开发者中心生成的cer证书去香蕉云编先的,如下图所示:

完成上面6个步骤,p12私钥证书文件就创建完毕了。

还有profile文件需要创建。

7)登录苹果开发者中心,找到Identifiers模块,创建一个应用。
注意,创建应用的时候,填写的应用的APPID,需要填写一个java格式的包名,一般是com.xxname.xxapp这样的格式。
这个appId,是跟hbuilderx的云打包里面的包名对应的,需要一致。

8)创建profile文件,在苹果开发者中心,找到profile模块,就可以创建profile了。
在这里需要提醒的是,创建profile的时候,假如选择app store connect类型,就是创建上架类型的profile。
假如创建的是Ad hoc类型,就是真机测试类型,可以用来给团队其他成员安装测试的。生成ad hoc类型的话,可以放到香蕉云编或者蒲公英这种测试平台来扫码安装。

创建profile的过程还需要绑定APPID(应用)和绑定Certificate(证书)的,就是绑定前几个创建的应用和证书,假如你有多个应用或多个证书,可别选错了。

假如选择的是ad hoc类型,它提示还需要绑定测试设备的udid的,你还是提前获取到你团队的所有udid,再去创建测试类型的profile文件。因为添加了新成员,profile又需要重新创建的,重下下载profile文件的。

获取udid的最简单的方法是使用ios测试设备,扫描香蕉云编获取udid的工具,根据它的提示来获取udid:
https://www.yunedit.com/udid

好了,完成上面的8个步骤,证书和profile文件应该就创建完了。

收起阅读 »