diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/ComponentData.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/ComponentData.ets index 6d5a4088c..108e2c242 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/ComponentData.ets +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/ComponentData.ets @@ -179,6 +179,22 @@ const INFORMATION_PRESENTATION_AND_DYNAMIC_EFFECTS: ThirdLevelCategory = { title: $r('app.string.data_panel'), url: 'pages/components/informationPresentationAndDynamicEffects/dataPanelSample/DataPanelSample' + }, + { + title: $r('app.string.scroll_To_effect'), + url: "pages/components/informationPresentationAndDynamicEffects/scrollToSample/ScrollToSample" + }, + { + title: $r('app.string.tabs_switch_effect'), + url: "pages/components/informationPresentationAndDynamicEffects/tapsSwitchSample/TapsSwitchSample" + }, + { + title: $r('app.string.image_fit_Full_effect'), + url: "pages/components/informationPresentationAndDynamicEffects/imageFitFullSample/ImageFitFullSample" + }, + { + title: $r('app.string.particle_effect'), + url: "pages/components/informationPresentationAndDynamicEffects/particleSample/ParticleSample" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/imageFitFullSample/ImageFitFullSample.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/imageFitFullSample/ImageFitFullSample.ets new file mode 100644 index 000000000..cd12f2cac --- /dev/null +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/imageFitFullSample/ImageFitFullSample.ets @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TitleBar } from '../../../../common/TitleBar'; + +@Extend(Radio) function fancyRadio(){ + .height(25) + .width(25) +} + +@Entry +@Component +struct ImageFitFullSample { + @State message: string = 'Hello World'; + @State imageFit: ImageFit = ImageFit.None; + + build() { + Column() { + TitleBar({ title: $r('app.string.image_fit_Full_effect') }); + Image($r('app.media.flower')) + .width('100%') + .height('30%') + .objectFit(this.imageFit) + .margin({ top: '30%' }) + .borderWidth(1) + .alignSelf(ItemAlign.Center); + + Grid() { + GridItem() { + Column() { + Text('Contain') + Radio({ value: 'RadioContain', group: 'radioGroup' }) + .fancyRadio() + .checked(false) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.Contain; + }); + }; + }; + GridItem() { + Column() { + Text('Cover') + Radio({ value: 'RadioCover', group: 'radioGroup' }) + .fancyRadio() + .checked(false) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.Cover; + }); + }; + }; + GridItem() { + Column() { + Text('Auto') + Radio({ value: 'RadioAuto', group: 'radioGroup' }) + .fancyRadio() + .checked(false) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.Auto; + }); + }; + }; + GridItem() { + Column() { + Text('Fill') + Radio({ value: 'RadioFill', group: 'radioGroup' }) + .fancyRadio() + .checked(false) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.Fill; + }); + }; + }; + GridItem() { + Column() { + Text('ScaleDown') + Radio({ value: 'RadioScaleDown', group: 'radioGroup' }) + .fancyRadio() + .checked(false) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.ScaleDown; + }); + }; + }; + GridItem() { + Column() { + Text('None') + Radio({ value: 'RadioNone', group: 'radioGroup' }) + .fancyRadio() + .checked(true) + .onChange((isChecked: boolean) => { + this.imageFit = ImageFit.None; + }); + }; + }; + } + .columnsTemplate('1fr 1fr 1fr') + .width('70%'); + } + .padding({top:24, bottom: 12}); + + } +} \ No newline at end of file diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/particleSample/ParticleSample.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/particleSample/ParticleSample.ets new file mode 100644 index 000000000..0737ed12e --- /dev/null +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/particleSample/ParticleSample.ets @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TitleBar } from '../../../../common/TitleBar'; + +let sampleParticleEngine = {}; + +@Entry +@Component +struct ParticleSample { + private settings: RenderingContextSettings = new RenderingContextSettings(true); + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); + private spawn: boolean = false; + private interval: number; + + elevation(x, y, z) { + let distance = Math.sqrt(x * x + y * y + z * z); + if (distance && z / distance >= -1 && z / distance <= 1){ + return Math.acos(z / distance); + } + return 0.00000001; + } + + rgb(colorRGBData) { + colorRGBData += 0.000001; + // generate rgb value by random for particles + let r = Math.round((0.5 + Math.sin(colorRGBData) * 0.5) * 16); + let g = Math.round((0.5 + Math.cos(colorRGBData) * 0.5) * 16); + let b = Math.round((0.5 - Math.sin(colorRGBData) * 0.5) * 16); + return '#' + r.toString(16) + g.toString(16) + b.toString(16); + } + + interpolateColors(RGB1, RGB2, degree) { + let w2 = degree; + let w1 = 1 - w2; + return [w1 * RGB1[0] + w2 * RGB2[0], w1 * RGB1[1] + w2 * RGB2[1], w1 * RGB1[2] + w2 * RGB2[2]]; + } + + rgbArray(colorRGBData) { + colorRGBData += 0.000001; + // generate rgb value by random for particles and returned as an array + let r = Math.round((0.5 + Math.sin(colorRGBData) * 0.5) * 256); + let g = Math.round((0.5 + Math.cos(colorRGBData) * 0.5) * 256); + let b = Math.round((0.5 - Math.sin(colorRGBData) * 0.5) * 256); + return [r, g, b]; + } + + colorString(colorArray) { + // generate rgb value by random with a generated rgb array for particles and returned as a string + let r = Math.round(colorArray[0]); + let g = Math.round(colorArray[1]); + let b = Math.round(colorArray[2]); + return '#' + ('0' + r.toString(16)).slice(-2) + ('0' + g.toString(16)).slice(-2) + ('0' + b.toString(16)).slice(-2); + } + + particleEnginePerform(particleEngine) { + if (particleEngine.points.length < particleEngine.initParticles) { + for (let i = 0; i < 5; ++i) { + this.particleItemSpawn(particleEngine); + } + } + let p, d, t; + + // generate particle move path for animation which is a spiral orbit + p = Math.atan2(particleEngine.camX, particleEngine.camZ); + d = Math.sqrt(particleEngine.camX * particleEngine.camX + particleEngine.camZ * particleEngine.camZ); + // move by each frame + d -= Math.sin(particleEngine.frameNo / 80) / 25; + t = Math.cos(particleEngine.frameNo / 300) / 165; + particleEngine.camX = Math.sin(p + t) * d; + particleEngine.camZ = Math.cos(p + t) * d; + particleEngine.camY = -Math.sin(particleEngine.frameNo / 220) * 15; + particleEngine.yaw = Math.PI + p + t; + particleEngine.pitch = this.elevation(particleEngine.camX, particleEngine.camZ, particleEngine.camY) - Math.PI / 2; + + let x, y, z; + for (let i = 0; i < particleEngine.points.length; ++i) { + x = particleEngine.points[i].x; + y = particleEngine.points[i].y; + z = particleEngine.points[i].z; + // distance between particles, 1.0075 is the justify number + d = Math.sqrt(x * x + z * z) / 1.0075; + t = 0.1 / (1 + d * d / 5); + p = Math.atan2(x, z) + t; + particleEngine.points[i].x = Math.sin(p) * d; + particleEngine.points[i].z = Math.cos(p) * d; + particleEngine.points[i].y += particleEngine.points[i].vy * t * ((Math.sqrt(particleEngine.distributionRadius) - d) * 2); + if (particleEngine.points[i].y > particleEngine.vortexHeight / 2 || d < 0.25) { + particleEngine.points.splice(i, 1); + this.particleItemSpawn(particleEngine); + } + } + } + + TrackSpawn(x, y, z, particleEngine) { + let p, d; + x -= particleEngine.camX; + y -= particleEngine.camY - 8; + z -= particleEngine.camZ; + p = Math.atan2(x, z); + d = Math.sqrt(x * x + z * z); + x = Math.sin(p - particleEngine.yaw) * d; + z = Math.cos(p - particleEngine.yaw) * d; + p = Math.atan2(y, z); + d = Math.sqrt(y * y + z * z); + y = Math.sin(p - particleEngine.pitch) * d; + z = Math.cos(p - particleEngine.pitch) * d; + let rx1 = -1000; + let ry1 = 1; + let rx2 = 1000; + let ry2 = 1; + let rx3 = 0; + let ry3 = 0; + let rx4 = x; + let ry4 = z; + let uc = (ry4 - ry3) * (rx2 - rx1) - (rx4 - rx3) * (ry2 - ry1); + let ua = ((rx4 - rx3) * (ry1 - ry3) - (ry4 - ry3) * (rx1 - rx3)) / uc; + let ub = ((rx2 - rx1) * (ry1 - ry3) - (ry2 - ry1) * (rx1 - rx3)) / uc; + if (!z) { + z = 0.000000001; + } + if (ua > 0 && ua < 1 && ub > 0 && ub < 1) { + return { + x: particleEngine.cx + (rx1 + ua * (rx2 - rx1)) * particleEngine.scale, + y: particleEngine.cy + y / z * particleEngine.scale, + d: (x * x + y * y + z * z) + }; + } else { + return { d: -1 }; + } + } + + sortMethod(a, b) { + return b.distance - a.distance; + } + + particleSpawn(particleEngine) { + particleEngine.ctx.globalAlpha = 0.15; + particleEngine.ctx.fillStyle = '#000'; + particleEngine.ctx.globalCompositeOperation = 'source-over'; + particleEngine.ctx.fillRect(0, 0, particleEngine.width, particleEngine.height); + + let point, x, y, z, a, size, d; + for (let i = 0; i < particleEngine.points.length; ++i) { + x = particleEngine.points[i].x; + y = particleEngine.points[i].y; + z = particleEngine.points[i].z; + point = this.TrackSpawn(x, y, z, particleEngine); + if (point.d !== -1) { + particleEngine.points[i].distance = point.d; + size = 1 + particleEngine.points[i].radius / (1 + point.d); + d = Math.abs(particleEngine.points[i].y); + a = 0.8 - Math.pow(d / (particleEngine.vortexHeight / 2), 1000) * 0.8; + particleEngine.ctx.globalAlpha = a >= 0 && a <= 1 ? a : 0; + particleEngine.ctx.fillStyle = this.rgb(particleEngine.points[i].color); + if (point.x > -1 && point.x < particleEngine.width && point.y > -1 && point.y < particleEngine.height) { + particleEngine.ctx.fillRect(point.x - size / 2, point.y - size / 2, size, size); + } + } + } + particleEngine.points.sort(this.sortMethod); + } + + particleItemSpawn(particleEngine) { + let p; + let ls; + let pt = { + x: 0.0, + y: 0.0, + vy: 0.0, + z: 0.0, + radius: 0.0, + color: 0.0, + }; + // vortex points x, y, z(analog) values generation + p = Math.PI * 2 * Math.random(); + ls = Math.sqrt(Math.random() * particleEngine.distributionRadius); + pt.x = Math.sin(p) * ls; + pt.y = -particleEngine.vortexHeight / 2; + pt.vy = particleEngine.initV / 20 + Math.random() * particleEngine.initV; + pt.z = Math.cos(p) * ls; + pt.radius = 200 + 800 * Math.random(); + pt.color = pt.radius / 1000 + particleEngine.frameNo / 250; + particleEngine.points.push(pt); + } + + init(particleEngine) { + particleEngine.ctx = this.context; + particleEngine.width = this.context.width; + particleEngine.height = this.context.height; + particleEngine.frameNo = 0; + + // canvas x + particleEngine.camX = 0; + // canvas y + particleEngine.camY = 0; + // canvas analog z + particleEngine.camZ = -14; + // particle curve rate of its orbits + particleEngine.pitch = this.elevation(particleEngine.camX, particleEngine.camZ, particleEngine.camY) - Math.PI / 2; + particleEngine.yaw = 0; + // central axis of canvas width + particleEngine.cx = particleEngine.width / 2; + // central axis of canvas height + particleEngine.cy = particleEngine.height / 2; + // particle orbits generation scale + particleEngine.scale = 500; + + particleEngine.points = []; + // max particles to be generated + particleEngine.initParticles = 80; + // y shifting rate for each frame + particleEngine.initV = 0.01; + // max particles generation radius + particleEngine.distributionRadius = 800; + // vortex generated height + particleEngine.vortexHeight = 25; + } + + particleFrameGenerate(particleEngine) { + particleEngine.frameNo++; + this.particleEnginePerform(particleEngine); + this.particleSpawn(particleEngine); + } + + animationOn() { + this.interval = setInterval(() => { + this.particleFrameGenerate(sampleParticleEngine); + }, 20); + } + + build(){ + Column() { + TitleBar({ title: $r('app.string.particle_effect') }); + Column() { + Canvas(this.context) + .width('90%') + .height('90%') + .borderRadius(24) + .backgroundColor(Color.Black); + } + .padding(12) + .margin({ left: 12, right: 12, top: 24, bottom: 24 }) + .borderRadius(24) + .width('90%') + .backgroundColor(Color.Black) + .height('70%'); + + Grid() { + GridItem() { + Button($r('app.string.particle_spawn')) + .onClick(() => { + if (this.spawn !== true) { + this.init(sampleParticleEngine); + this.animationOn(); + this.spawn = true; + } + }) + .width('100%'); + } + + GridItem() { + Button($r('app.string.particle_spawn_stop')) + .onClick(() => { + this.spawn = false; + clearInterval(this.interval); + }) + .width('100%'); + } + } + .columnsTemplate('1fr 1fr') + .columnsGap(12) + .padding({ left: 24, right: 24, bottom: 24 }) + .width('100%'); + } + .backgroundColor($r('app.color.background_shallow_grey')); + } + + aboutToDisappear() { + clearInterval(this.interval); + } +} \ No newline at end of file diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/scrollToSample/ScrollToSample.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/scrollToSample/ScrollToSample.ets new file mode 100644 index 000000000..fdd19a89e --- /dev/null +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/scrollToSample/ScrollToSample.ets @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TitleBar } from '../../../../common/TitleBar'; + +@Extend(Text) function fancyText() { + .width('90%') + .height(80) + .backgroundColor($r('app.color.scroll_item_color')) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) +} + +@Extend(Text) function leftTitleStyle() { + .fontColor($r('app.color.sub_title_color')) + .fontWeight(FontWeight.Medium) + .fontSize(20) + .height(22) + .letterSpacing('40%') + .alignSelf(ItemAlign.Start) + .margin({ left: 24, top: 12 }) +} + +@Extend(Text) function gridText() { + .fontSize(16) + .backgroundColor($r('app.color.scroll_grid_item_color')) + .height(80) + .textAlign(TextAlign.Center) +} + +@Extend(Column) function itemColumn() { + .height('40%') + .backgroundColor($r('app.color.white')) + .alignItems(HorizontalAlign.Start) +} + +@Extend(Button) function sampleButton() { + .height(40) + .margin(12) + .fontColor(Color.White) + .fontSize(15) +} + +@Entry +@Component +struct ScrollToSample { + private scroller: Scroller = new Scroller(); + private mScroller: Scroller = new Scroller(); + private listScroller: Scroller = new Scroller(); + private gridScroller: Scroller = new Scroller(); + private waterFlowScroller: Scroller = new Scroller(); + private scrollArr: Array = new Array(); + + aboutToAppear() { + for (let i = 0; i < 24; i++) { + this.scrollArr.push(i) + } + } + + @Builder itemFoot() { + Column() { + Text(`Footer`) + .fontSize(10) + .backgroundColor(Color.Red) + .width(50) + .height(50) + .align(Alignment.Center) + .margin({ top: 6 }) + } + } + build() { + Column() { + TitleBar({ title: $r('app.string.scroll_To_effect') }); + Scroll(this.scroller) { + Column({ space: 10 }) { + Column() { + Text($r('app.string.scroller')) + .leftTitleStyle(); + Button($r('app.string.scroll_To_effect')) + .sampleButton() + .alignSelf(ItemAlign.Center) + .onClick(() => { + if (this.mScroller.currentOffset().yOffset === 0) { + this.mScroller.scrollTo({ xOffset: 0, yOffset: this.mScroller.currentOffset().yOffset + 300, + animation: { duration: 800, curve: Curve.Linear } + },); + } else { + this.mScroller.scrollTo({ xOffset: 0, yOffset: 0, + animation: { duration: 800, curve: Curve.Linear } + },); + } + }).id('scroll_to_effect_scroller'); + Scroll(this.mScroller) { + Column() { + ForEach(this.scrollArr, (item) => { + Text(item.toString()) + .fancyText(); + }, item => item); + } + .padding({ top: 6, bottom: 12 }) + .width('100%') + .alignSelf(ItemAlign.Center) + .backgroundColor(Color.White); + } + .alignSelf(ItemAlign.Center) + .height('70%') + .width('92%') + .borderRadius(24) + .backgroundColor(Color.White); + + } + .itemColumn() + .width('100%') + .backgroundColor($r('app.color.background_shallow_grey')); + + Column() { + Text($r('app.string.list')) + .leftTitleStyle(); + Button($r('app.string.scroll_To_effect')) + .sampleButton() + .alignSelf(ItemAlign.Center) + .onClick(() => { + if (this.listScroller.currentOffset().yOffset === 0) { + this.listScroller.scrollTo({ xOffset: 0, yOffset: this.listScroller.currentOffset().yOffset + 300, + animation: { duration: 800, curve: Curve.Linear } + },); + } else { + this.listScroller.scrollTo({ xOffset: 0, yOffset: 0, + animation: { duration: 800, curve: Curve.Linear } + },); + } + }).id('scroll_to_effect_list'); + + List({ scroller: this.listScroller }) { + ForEach(this.scrollArr, (item) => { + ListItem() { + Text(item.toString()) + .fancyText(); + } + .width('100%') + .alignSelf(ItemAlign.Center) + .backgroundColor(Color.White); + }, item => item); + + } + .alignSelf(ItemAlign.Center) + .height('70%') + .width('92%') + .borderRadius(24) + .backgroundColor(Color.White); + + } + .itemColumn() + .width('100%') + .backgroundColor($r('app.color.background_shallow_grey')); + + Column() { + Text($r('app.string.grid')) + .leftTitleStyle(); + Button($r('app.string.scroll_To_effect')) + .sampleButton() + .alignSelf(ItemAlign.Center) + .onClick(() => { + if (this.gridScroller.currentOffset().yOffset <= 0) { + this.gridScroller.scrollTo({ xOffset: 0, yOffset: this.gridScroller.currentOffset().yOffset + 500, + animation: { duration: 2000, curve: Curve.Linear } + },); + } else { + this.gridScroller.scrollTo({ xOffset: 0, yOffset: 0, + animation: { duration: 2000, curve: Curve.Linear } + },); + } + }).id('scroll_to_effect_grid'); + Grid(this.gridScroller) { + ForEach(this.scrollArr, (day: string) => { + GridItem() { + Text('world') + .width('100%') + .gridText(); + }; + }, day => day); + } + .alignSelf(ItemAlign.Center) + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(12) + .rowsGap(12) + .height('70%') + .width('92%') + .borderRadius(24) + .padding({ left: 12, right: 12, top: 12, bottom: 12 }) + .backgroundColor(Color.White); + + } + .itemColumn() + .width('100%') + .backgroundColor($r('app.color.background_shallow_grey')); + + Column() { + Text($r('app.string.waterFlow')) + .leftTitleStyle(); + Button($r('app.string.scroll_To_effect')) + .sampleButton() + .alignSelf(ItemAlign.Center) + .onClick(() => { + if (this.waterFlowScroller.currentOffset().yOffset <= 0) { + this.waterFlowScroller.scrollTo({ + xOffset: 0, + yOffset: this.waterFlowScroller.currentOffset().yOffset + 500, + animation: { duration: 2000, curve: Curve.Linear } + },); + } else { + this.waterFlowScroller.scrollTo({ + xOffset: 0, + yOffset: 0, + animation: { duration: 2000, curve: Curve.Linear } + },); + } + }).id('scroll_to_effect_waterflow'); + WaterFlow({ footer: this.itemFoot.bind(this), scroller: this.waterFlowScroller }) { + ForEach(this.scrollArr, (day: string) => { + FlowItem() { + Text('hello') + .width('30%') + .gridText(); + }; + }, day => day); + } + .alignSelf(ItemAlign.Center) + .columnsTemplate('1fr 1fr 1fr') + .layoutDirection(FlexDirection.Column) + .columnsGap(12) + .rowsGap(12) + .height('70%') + .width('92%') + .borderRadius(24) + .padding({ left: 12, right: 12, top: 12, bottom: 12}) + .backgroundColor(Color.White); + } + .itemColumn() + .width('100%') + .backgroundColor($r('app.color.background_shallow_grey')); + } + .backgroundColor($r('app.color.background_shallow_grey')) + .width('100%'); + } + .padding({left: 10, right: 10, bottom: 24}) + .height('90%') + .backgroundColor($r('app.color.background_shallow_grey')) + .scrollable(ScrollDirection.Vertical); + } + .width('100%') + .padding({bottom: 12}) + .backgroundColor($r('app.color.background_shallow_grey')); + } +} + diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/tapsSwitchSample/TapsSwitchSample.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/tapsSwitchSample/TapsSwitchSample.ets new file mode 100644 index 000000000..d27df421c --- /dev/null +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/ets/pages/components/informationPresentationAndDynamicEffects/tapsSwitchSample/TapsSwitchSample.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TitleBar } from '../../../../common/TitleBar'; + +@Entry +@Component +struct TapsSwitchSample { + @State fontColor: string = '#182431' + @State selectedFontColor: string = '#007DFF' + @State currentIndex: number = 0 + private controller: TabsController = new TabsController() + + @Builder TabBuilder(index: number, name: string) { + Column() { + Text(name) + .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) + .fontSize(16) + .fontWeight(this.currentIndex === index ? 500 : 400) + .lineHeight(22) + .margin({ top: 17, bottom: 7 }); + Divider() + .strokeWidth(2) + .color('#007DFF') + .opacity(this.currentIndex === index ? 1 : 0); + }.width('100%'); + } + + build() { + Column() { + TitleBar({ title: $r('app.string.tabs_switch_effect') }); + Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { + TabContent() { + Column().width('100%').height('100%').backgroundColor('#00CB87') + }.tabBar(this.TabBuilder(0, 'green')); + + TabContent() { + Column().width('100%').height('100%').backgroundColor('#007DFF') + }.tabBar(this.TabBuilder(1, 'blue')); + + TabContent() { + Column().width('100%').height('100%').backgroundColor('#FFBF00') + }.tabBar(this.TabBuilder(2, 'yellow')); + + TabContent() { + Column().width('100%').height('100%').backgroundColor('#E67C92') + }.tabBar(this.TabBuilder(3, 'pink')); + } + .vertical(false) + .barMode(BarMode.Fixed) + .barWidth(360) + .barHeight(56) + .animationDuration(500) + .onChange((index: number) => { + this.currentIndex = index + }) + .width('100%') + .backgroundColor('#F1F3F5'); + } + .padding({bottom: 12}) + .width('100%'); + } + +} \ No newline at end of file diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/color.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/color.json index 21267f0b1..7973c3d93 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/color.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/color.json @@ -212,6 +212,18 @@ { "name": "canvas_bg_color", "value": "#00ffff" + }, + { + "name": "scroll_to_button_color", + "value": "#ff55c6f5" + }, + { + "name": "scroll_item_color", + "value": "#ff2a78db" + }, + { + "name": "scroll_grid_item_color", + "value": "#F9CF93" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/string.json index a538d0837..d34d37b27 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/element/string.json @@ -3412,6 +3412,47 @@ { "name": "canvas_imageSmoothingQuality", "value": "imageSmoothingQuality" + }, + // scrollTo 动效增强 + { + "name": "scroll_To_effect", + "value": "ScrollTo effect" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs switch effect" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full effect" + }, + { + "name": "particle_effect", + "value": "Particle Effect" + }, + { + "name": "particle_spawn", + "value": "Spawn" + }, + { + "name": "particle_spawn_stop", + "value": "Stop" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/flower.jpg b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/flower.jpg new file mode 100644 index 000000000..988f97227 Binary files /dev/null and b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/flower.jpg differ diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/ic_lifecycle.png b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/ic_lifecycle.png new file mode 100644 index 000000000..dd29fe5ff Binary files /dev/null and b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/media/ic_lifecycle.png differ diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/profile/main_pages.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/profile/main_pages.json index 0eaa12862..a416453d0 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/profile/main_pages.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/base/profile/main_pages.json @@ -77,6 +77,10 @@ "pages/components/informationPresentationAndDynamicEffects/progressSample/ProgressSample", "pages/components/informationPresentationAndDynamicEffects/gaugeSample/GaugeSample", "pages/components/informationPresentationAndDynamicEffects/dataPanelSample/DataPanelSample", + "pages/components/informationPresentationAndDynamicEffects/scrollToSample/ScrollToSample", + "pages/components/informationPresentationAndDynamicEffects/tapsSwitchSample/TapsSwitchSample", + "pages/components/informationPresentationAndDynamicEffects/imageFitFullSample/ImageFitFullSample", + "pages/components/informationPresentationAndDynamicEffects/particleSample/ParticleSample", "pages/components/buttonAndSelection/ratingSample/RatingSample", "pages/components/buttonAndSelection/counterSample/CounterSample", "pages/components/buttonAndSelection/timePickerSample/TimePickerSample", @@ -100,4 +104,4 @@ "pages/universal/gesture/swipeSample/SwipeSample", "pages/universal/gesture/combinedSample/CombinedSample" ] -} \ No newline at end of file +} diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/en/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/en/element/string.json index 63a3440f7..2431d3a4d 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/en/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/en/element/string.json @@ -2482,6 +2482,47 @@ { "name": "canvas_show_message", "value": "Printed to the console" + }, + // scrollTo 动效增强 + { + "name": "scroll_To_effect", + "value": "ScrollTo effect" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs switch effect" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full effect" + }, + { + "name": "particle_effect", + "value": "Particle Effect" + }, + { + "name": "particle_spawn", + "value": "Spawn" + }, + { + "name": "particle_spawn_stop", + "value": "Stop" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/zh/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/zh/element/string.json index a2dc89538..a158a2044 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/zh/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/main/resources/zh/element/string.json @@ -2659,6 +2659,47 @@ { "name": "canvas_show_message", "value": "已经打印到控制台" + }, + // scrollTo 动效增强 + { + "name": "scroll_To_effect", + "value": "ScrollTo 动效" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs 模糊切换" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full 动效" + }, + { + "name": "particle_effect", + "value": "Particle 粒子效果" + }, + { + "name": "particle_spawn", + "value": "生成" + }, + { + "name": "particle_spawn_stop", + "value": "停止" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/ets/test/Ability.test.ets b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/ets/test/Ability.test.ets index 9be856aad..84755ec3c 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/ets/test/Ability.test.ets +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/ets/test/Ability.test.ets @@ -1013,6 +1013,164 @@ export default function abilityTest() { Logger.info(BUNDLE + testName + ' end'); }) + /** + * ScrollTo 动效 + */ + it(BUNDLE + 'ScrollTo_effect_001', 0, async function () { + let testName = 'ScrollToEffect'; + Logger.info(BUNDLE + testName + ' begin'); + + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + // 进入Scroll To 动效 + let atom = await manager.getStringValue($r('app.string.scroll_To_effect')) + + let button = await driver.findComponent(ON.text(atom)); + if (!button) { + // 如果没展开 就展开 + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.information_presentation_and_dynamic_effects'))); + } + await driver.swipe(100, 1000, 100, 400, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(atom); + + await driver.delayMs(DELAY_TIME); + // 点击按钮 + await checkButtonAndClickWithID('scroll_to_effect_scroller'); + await checkButtonAndClickWithID('scroll_to_effect_list'); + await driver.swipe(100, 1000, 100, 400, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithID('scroll_to_effect_grid'); + await checkButtonAndClickWithID('scroll_to_effect_waterflow'); + + let backBtn = await driver.findComponent(ON.id('backBtn')); + if(!backBtn) + { + Logger.error('No backbtn found in ' + testName); + } + // 返回 + await backBtn.click(); + await driver.delayMs(500); + + Logger.info(BUNDLE + testName + ' end'); + }) + + + /** + * Tab 模糊切换 + */ + it(BUNDLE + 'Tab_switch_effect_001', 0, async function () { + let testName = 'TabToEffect'; + Logger.info(BUNDLE + testName + ' begin'); + + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + + // 进入Scroll To 动效 + let atom = await manager.getStringValue($r('app.string.tabs_switch_effect')) + + let button = await driver.findComponent(ON.text(atom)); + if (!button) { + // 如果没展开 就展开 + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.information_presentation_and_dynamic_effects'))); + } + await driver.swipe(100, 1000, 100, 400, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(atom); + + // 点击按钮 + await checkButtonAndClickWithText('green'); + await checkButtonAndClickWithText('blue'); + await checkButtonAndClickWithText('yellow'); + await checkButtonAndClickWithText('pink'); + + let backBtn = await driver.findComponent(ON.id('backBtn')); + if (!backBtn) + { + Logger.error('Cannot find backbtn in this page'); + } + // 返回 + await backBtn.click(); + await driver.delayMs(500); + + Logger.info(BUNDLE + testName + ' end'); + }) + + /** + * ImageFit 切换 + */ + it(BUNDLE + 'ImageFit_effect_001', 0, async function () { + let testName = 'ImageFitEffect'; + Logger.info(BUNDLE + testName + ' begin'); + + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + + // 进入Scroll To 动效 + let atom = await manager.getStringValue($r('app.string.image_fit_Full_effect')) + + let button = await driver.findComponent(ON.text(atom)); + if (!button) { + // 如果没展开 就展开 + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.information_presentation_and_dynamic_effects'))); + } + await driver.swipe(100, 1000, 100, 400, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(atom); + + // 点击按钮 + await checkButtonAndClickWithText('RadioContain'); + await checkButtonAndClickWithText('RadioCover'); + await checkButtonAndClickWithText('RadioAuto'); + await checkButtonAndClickWithText('RadioFill'); + await checkButtonAndClickWithText('RadioScaleDown'); + await checkButtonAndClickWithText('RadioNone'); + + let backBtn = await driver.findComponent(ON.id('backBtn')); + // 返回 + await backBtn.click(); + await driver.delayMs(500); + + Logger.info(BUNDLE + testName + ' end'); + }) + + /** + * Particle 粒子效果 + */ + it(BUNDLE + 'Particle_effect_001', 0, async function () { + let testName = 'Particle Effect'; + Logger.info(BUNDLE + testName + ' begin'); + + // 进入Scroll To 动效 + let atom = await manager.getStringValue($r('app.string.particle_effect')) + + let button = await driver.findComponent(ON.text(atom)); + if (!button) { + // 如果没展开 就展开 + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.information_presentation_and_dynamic_effects'))); + } + await driver.swipe(100, 1000, 100, 400, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(atom); + await driver.delayMs(DELAY_TIME); + + // 点击按钮 + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.particle_spawn'))); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.particle_spawn_stop'))); + + let backBtn = await driver.findComponent(ON.id('backBtn')); + // 返回 + await backBtn.click(); + await driver.delayMs(500); + + await driver.swipe(100, 400, 100, 1000, 5000); + await driver.delayMs(DELAY_TIME); + await checkButtonAndClickWithText(await manager.getStringValue($r('app.string.information_presentation_and_dynamic_effects'))); + Logger.info(BUNDLE + testName + ' end'); + }) + + /** * ImageSpan 行内图像 */ @@ -3003,4 +3161,4 @@ export default function abilityTest() { Logger.info("Sample_ComponentCollection test end"); }) }) -} \ No newline at end of file +} diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/base/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/base/element/string.json index 2936359d3..65025f06d 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/base/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/base/element/string.json @@ -3356,6 +3356,47 @@ { "name": "canvas_imageSmoothingQuality", "value": "imageSmoothingQuality" + }, + // scrollTo 动效增强 + { + "name": "scroll_To_effect", + "value": "ScrollTo effect" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs switch effect" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full effect" + }, + { + "name": "particle_effect", + "value": "Particle Effect" + }, + { + "name": "particle_spawn", + "value": "Spawn" + }, + { + "name": "particle_spawn_stop", + "value": "Stop" } ] } diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/en/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/en/element/string.json index c934a9ab0..d09ad4e8d 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/en/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/en/element/string.json @@ -2146,6 +2146,46 @@ { "name": "canvas_show_message", "value": "Printed to the console" + }, + { + "name": "scroll_To_effect", + "value": "ScrollTo effect" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs switch effect" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full effect" + }, + { + "name": "particle_effect", + "value": "Particle Effect" + }, + { + "name": "particle_spawn", + "value": "Spawn" + }, + { + "name": "particle_spawn_stop", + "value": "Stop" } ] } \ No newline at end of file diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/zh/element/string.json b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/zh/element/string.json index b509d3a93..49dbe723c 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/zh/element/string.json +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/entry/src/ohosTest/resources/zh/element/string.json @@ -1826,6 +1826,47 @@ { "name": "canvas_show_message", "value": "已经打印到控制台" + }, + // scrollTo 动效增强 + { + "name": "scroll_To_effect", + "value": "ScrollTo 动效" + }, + { + "name": "scroller", + "value": "Scroller" + }, + { + "name": "list", + "value": "List" + }, + { + "name": "grid", + "value": "Grid" + }, + { + "name": "waterFlow", + "value": "WaterFlow" + }, + { + "name": "tabs_switch_effect", + "value": "Tabs 模糊切换" + }, + { + "name": "image_fit_Full_effect", + "value": "Image fit/full 动效" + }, + { + "name": "particle_effect", + "value": "Particle 粒子效果" + }, + { + "name": "particle_spawn", + "value": "生成" + }, + { + "name": "particle_spawn_stop", + "value": "停止" } ] } \ No newline at end of file diff --git a/code/UI/ArkTsComponentCollection/ComponentCollection/ohosTest.md b/code/UI/ArkTsComponentCollection/ComponentCollection/ohosTest.md index a8eb98db6..33fa945d4 100644 --- a/code/UI/ArkTsComponentCollection/ComponentCollection/ohosTest.md +++ b/code/UI/ArkTsComponentCollection/ComponentCollection/ohosTest.md @@ -24,6 +24,10 @@ | 验证Progress 进度条 | 展开信息展示与动效,进入Progress 进度条 | 调整进度条的进度 | 正确显示进度条的进度 | 是 | Pass | | 验证Gauge 仪表盘 | 展开信息展示与动效,进入Gauge 仪表盘 | 调整仪表盘的value和strokeWidth | 正确改变仪表盘的属性 | 是 | Pass | | 验证DataPanel 数据面板 | 展开信息展示与动效,进入DataPanel 数据面板 | | 正确显示数据面板动画 | 是 | Pass | +| 验证ScrollTo 动效 | 展开信息展示与动效,进入ScrollTo 动效 | 点击ScrollTo动效按钮 | ScrollTo动效展示 | 是 | Pass | +| 验证Tab 模糊切换 | 展开信息展示与动效,进入Tab 模糊切换 | 点击Tab 进行模糊切换 | Tab 模糊切换成功 | 是 | Pass | +| 验证ImageFit 切换 | 展开信息展示与动效,进入ImageFit 切换 | 依次点击Radius按钮进行ImageFit模式切换 | ImageFit 模式切换成功 | 是 | Pass | +| 验证Particle粒子效果 | 展开信息展示与动效,进入Particle粒子效果 | 点击Particle粒子效果生成按钮 | Particle粒子效果生成成功 | 是 | Pass | | 验证Span 行内文本 | 展开文本与输入,进入Span 行内文本 | 依次调整字符间距,装饰线类型,颜色 | 依次改变对于属性 | 是 | Pass | | 验证TextInput 文本输入 | 展开文本与输入,进入TextInput 文本输入 | 在输入框输入文本 | 正确显示输入文本 | 是 | Pass | | 验证Text 文本 | 展开文本与输入,进入Text 文本 | 依次更改字符间距,行高,对其类型,超长文本显示方式,装饰线,字体颜色,大小写 | 依次更改对应属性 | 是 | Pass |