未验证 提交 95ef0d71 编写于 作者: O openharmony_ci 提交者: Gitee

!19117 【3.2-Release】翻译完成 18259+18500+18251+18230+18720+18044

Merge pull request !19117 from ester.zhou/C2-18259
......@@ -275,7 +275,7 @@ In addition to the [universal methods](js-components-common-methods.md), the fol
top:0,
},
dragstart(e){
prompt.showToast({
promptAction.showToast({
message: 'Start to be dragged'
})
},
......@@ -385,25 +385,25 @@ In addition to the [universal methods](js-components-common-methods.md), the fol
```js
// xxx.js
import prompt from '@system.prompt';
import promptAction from '@ohos.promptAction';
export default {
pinchstart(e){
prompt.showToast({
promptAction.showToast({
message: 'pinchstart!!!'
})
},
pinchupdate(e){
prompt.showToast({
promptAction.showToast({
message: 'Two-finger pinch update'
})
},
pinchend(e){
prompt.showToast({
promptAction.showToast({
message: 'Finished with two fingers pinching'
})
},
pinchcancel(e){
prompt.showToast({
promptAction.showToast({
message: 'Finger pinching is interrupted'
})
}
......
......@@ -24,9 +24,9 @@ Video(value: {src?: string | Resource, currentProgressRate?: number | string | P
| Name | Type | Mandatory| Description |
| ------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
| src | string \| [Resource](ts-types.md) | No | Path of the video source, which can be a local path or a URL.<br>The video resources can be stored in the **video** or **rawfile** folder under **resources**.<br>The path can include a **dataability://** prefix, which indicates that the path is provided by a Data ability. For details about the path, see [Data Ability Development](../../application-models/dataability-overview.md).<br>**NOTE**<br>The supported video formats are MP4, MKV, WebM, and TS.|
| src | string \| [Resource](ts-types.md) | No | Path of the video source, which can be a local path or a URL.<br>The video resources can be stored in the **video** or **rawfile** folder under **resources**.<br>The path can include a **dataability://** prefix, which indicates that the path is provided by a Data ability. For details about the path, see [Data Ability Development](../../application-models/dataability-overview.md).<br>- Strings with the **file:///data/storage** prefix are supported, which are used to read resources in the application sandbox. Ensure that the application has the read permission to the files in the specified path.<br>**NOTE**<br>The supported video formats are MP4, MKV, WebM, and TS. |
| currentProgressRate | number \| string \| PlaybackSpeed<sup>8+</sup> | No | Video playback speed.<br>**NOTE**<br>The value of the number type can only be **0.75**, **1.0**, **1.25**, **1.75**, or **2.0**.<br>Default value: 1.0 \| PlaybackSpeed.Speed_Forward_1_00_X |
| previewUri | string \|PixelMap \| [Resource](ts-types.md) | No | Path of the preview image. (The PixelMap type is not supported currently.) |
| previewUri | string \|PixelMap \| [Resource](ts-types.md) | No | Path of the preview image. |
| controller | [VideoController](#videocontroller) | No | Video controller. |
## PlaybackSpeed<sup>8+</sup>
......
......@@ -3,12 +3,12 @@
The framework provides four pixel units, with vp as the reference data unit.
| Name | Description |
| ---- | ---------------------------------------- |
| px | Physical pixel unit of the screen. |
| vp | Pixel unit specific to the screen density. Pixels in this unit are converted into physical pixels of the screen based on the screen pixel density. This unit is used for values whose unit is not specified.|
| fp | Font pixel, which is similar to vp and varies according to the system font size. |
| lpx | Logical pixel unit of the window. It is the ratio of the actual screen width to the logical width (configured by **designWidth**). For example, if **designWidth** is set to **720** (default value), then 1lpx is equal to 2px for a screen with an actual width of 1440 physical pixels.|
| Name| Description |
| ---- | ------------------------------------------------------------ |
| px | Physical pixel unit of the screen. |
| vp | Pixel unit specific to the screen density. Pixels in this unit are converted into physical pixels of the screen based on the screen pixel density. This unit is used for values whose unit is not specified. On a screen with an actual width of 1440 physical pixels, 1 vp is approximately equal to 3 px.|
| fp | Font pixel, which is similar to vp and varies according to the system font size.|
| lpx | Logical pixel unit of the window. It is the ratio of the actual screen width to the logical width (configured by **designWidth**). For example, if **designWidth** is set to **720** (default value), then 1 lpx is equal to 2 px for a screen with an actual width of 1440 physical pixels.|
## Pixel Unit Conversion
......@@ -37,33 +37,71 @@ struct Example {
Flex({ wrap: FlexWrap.Wrap }) {
Column() {
Text("width(220)")
.width(220).height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width(220)
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width('220px')")
.width('220px').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White)
.width('220px')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
}.margin(5)
Column() {
Text("width('220vp')")
.width('220vp').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width('220vp')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width('220lpx') designWidth:720")
.width('220lpx').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width('220lpx')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width(vp2px(220) + 'px')")
.width(vp2px(220) + 'px').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width(vp2px(220) + 'px')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("fontSize('12fp')")
.width(220).height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12fp')
.width(220)
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12fp')
}.margin(5)
Column() {
Text("width(px2vp(220))")
.width(px2vp(220))
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12fp')
}.margin(5)
}.width('100%')
}
......
......@@ -19,10 +19,10 @@ Configure the component transition animations for when a component is inserted o
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- | -------- |
| type | [TransitionType](ts-appendix-enums.md#transitiontype) | No| Transition type, which includes component addition and deletion by default.<br>Default value: **TransitionType.All**<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>If **type** is not specified, insertion and deletion use the same transition type.|
| opacity | number | No| Opacity of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>Default value: **1**<br>Value range: [0, 1]<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>A value less than 0 evaluates to the value **0**. A value greater than 1 evaluates to the value **1**.|
| opacity | number | No| Opacity of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>Default value: **1**<br>Value range: [0, 1]<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>A value less than 0 or greater than 1 evaluates to the value **1**.|
| translate | {<br>x? : number \| string,<br>y? : number \| string,<br>z? : number \| string<br>} | No| Translation of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>-**x**: distance to translate along the x-axis.<br>-**y**: distance to translate along the y-axis.<br>-**z**: distance to translate along the z-axis.<br>Since API version 9, this API is supported in ArkTS widgets.|
| scale | {<br>x? : number,<br>y? : number,<br>z? : number,<br>centerX? : number \| string,<br>centerY? : number \| string<br>} | No| Scaling of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>- **x**: scale factor along the x-axis.<br>- **y**: scale factor along the y-axis.<br>- **z**: scale factor along the z-axis.<br>- **centerX** and **centerY**: x coordinate and y coordinate of the scale center, respectively. The default values are both **"50%"**.<br>- If the center point is 0, it indicates the upper left corner of the component.<br>Since API version 9, this API is supported in ArkTS widgets.|
| rotate | {<br>x?: number,<br>y?: number,<br>z?: number,<br>angle?: number \| string,<br>centerX?: number \| string,<br>centerY?: number \| string<br>} | No| Rotation of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>- **x**: rotation vector along the x-axis.<br>- **y**: rotation vector along the y-axis.<br>- **z**: rotation vector along the z-axis.<br>- **centerX** and **centerY**: x coordinate and y coordinate of the rotation center, respectively. The default values are both **"50%"**.<br>- If the center point is (0, 0), it indicates the upper left corner of the component.<br>Since API version 9, this API is supported in ArkTS widgets.|
| rotate | {<br>x?: number,<br>y?: number,<br>z?: number,<br>angle: number \| string,<br>centerX?: number \| string,<br>centerY?: number \| string<br>} | No| Rotation of the component during transition, which is the value of the start point of insertion and the end point of deletion.<br>- **x**: rotation vector along the x-axis.<br>- **y**: rotation vector along the y-axis.<br>- **z**: rotation vector along the z-axis.<br>- **centerX** and **centerY**: x coordinate and y coordinate of the rotation center, respectively. The default values are both **"50%"**.<br>- If the center point is (0, 0), it indicates the upper left corner of the component.<br>Since API version 9, this API is supported in ArkTS widgets.|
## Example
......
# Animation Overview
The principle of animation is that the UI appearance is changed for multiple times within a period of time. Because human eyes generate visual persistence, what you finally see is a continuous animation. A change of the UI is called an animation frame, which corresponds to a screen refresh. An important indicator that determines the animation smoothness is the frame rate (FPS), that is, the number of animation frames per second. The higher the frame rate, the smoother the animation.
The principle of animation is that the UI appearance is changed for multiple times within a period of time. Because human eyes retain persistence of vision, what you finally see is a continuous animation. A change of the UI is called an animation frame, which corresponds to a screen refresh. An important indicator that determines the animation smoothness is the frame rate (FPS), that is, the number of animation frames per second. The higher the frame rate, the smoother the animation.
In ArkUI, an animation is generated by changing the attribute value and specifying the animation parameters. Animation parameters include parameters such as animation duration and change rule (that is, curve). After the attribute value changes, the original state is transited to the new state according to the animation parameter, that is, an animation is formed.
In ArkUI, an animation is generated by changing the attribute value and specifying the animation parameters. Animation parameters include animation duration, change rule (that is, curve), and more. After the attribute value changes, the original state is transited to the new state according to the animation parameters. In this way, an animation is formed.
The animation capability provided by the ArkUI can be classified into intra-page animation and inter-page animation based on the page classification mode. As shown in the following figure, an animation on a page refers to an animation that can occur on a page, and an animation between pages refers to an animation that occurs only when two pages jump.
The animation capability provided by ArkUI can be classified into intra-page animation and inter-page animation based on the page classification mode. As shown in the following figure, an animation on a page refers to an animation that can occur on a page, and an animation between pages refers to an animation that occurs only with redirection between pages.
Figure 1 Animation by page
**Figure 1** Animation by page
![en-us_image_0000001562700385](figures/en-us_image_0000001562700385.png)
Based on the basic capability, the animation can be divided into three parts: attribute animation, explicit animation, and transition animation. as shown in the following figure.
By capability, the animation can be divided into three parts: attribute animation, explicit animation, and transition animation, as shown in the following figure.
Figure 2 Animation classified by basic capability
**Figure 2** Animation classified by basic capability
![en-us_image_0000001562820753](figures/en-us_image_0000001562820753.png)
Based on the page classification mode and application scenarios, this document provides the usage methods and precautions of various animations for developers to quickly learn animations.
This topic will introduce you to the usage and precautions of animations by the preceding classification and use cases.
......@@ -13,7 +13,7 @@ You can create a **\<Video>** component by calling the following API:
Video(value: {src?: string | Resource, currentProgressRate?: number | string | PlaybackSpeed, previewUri?: string | PixelMap | Resource, controller?: VideoController})
```
Creates a **\<Video>** component. In this API, **src** indicates the path of the video source, **currentProgressRate** indicates the video playback speed, **previewUri** indicates the path of the preview image, and **controller** indicates the video controller . For details about how to load a video, see [Loading a Video](#loading-a-video).
Creates a **\<Video>** component. In this API, **src** indicates the path of the video source, **currentProgressRate** indicates the video playback speed, **previewUri** indicates the path of the preview image, and **controller** indicates the video controller . For details about how to load a video, see [Loading Video](#loading-video).
## Loading Video
......@@ -24,6 +24,7 @@ The **\<Video>** component supports both local and online videos.
### Loading a Local Video
- Common local video
To load a local video, specify the corresponding video file in the local **rawfile** directory, as shown in the following figure.
![en-us_image_0000001562700409](figures/en-us_image_0000001562700409.png)
......@@ -69,6 +70,27 @@ The **\<Video>** component supports both local and online videos.
}
```
### Loading a Video in the Application Sandbox
To load a video in the application sandbox, use a string with the **file:///data/storage** prefix. Ensure that the application has the read permission to the files in the specified path.
```ts
@Component
export struct VideoPlayer {
private controller: VideoController;
private videosrc: string = 'file:///data/storage/el2/base/haps/entry/files/show.mp4'
build() {
Column() {
Video({
src: this.videosrc,
controller: this.controller
})
}
}
}
```
### Loading an Online Video
......@@ -158,6 +180,7 @@ struct VideoPlayer{
The video controller is used to control video playback. For details, see [VideoController](../reference/arkui-ts/ts-media-components-video.md#videocontroller).
- Default controller
The default controller supports four basic features: start playback, pause playback, set the video playback position, and play the video in full screen.
```ts
......@@ -184,6 +207,7 @@ The video controller is used to control video playback. For details, see [VideoC
```
- Custom controller
To use a custom controller, disable the default controller, and then use components such as \<Button> and \<Slider> to customize the control and display. This type of controller is applicable to scenarios where customization requirements are involved.
```ts
......
......@@ -9,7 +9,7 @@
- Default focus
After an application opens or switches to a page, the first focusable component (if any) in the component tree of the page is the default focus. You can [set the default focus](#setting-default-focus) as needed.
After an application opens or switches to a page, the first focusable component (if any) in the component tree of the page is the default focus. You can [customize the default focus](#setting-default-focus) as needed.
- Focused
......@@ -619,7 +619,7 @@ tabIndex(index: number)
Use **tabIndex** to set the order for sequential Tab navigation. The default value is **0**. In Tab navigation, where Tab/Shift+Tab is used (the arrow keys do not affect the navigation), the focus system automatically obtains all components whose **tabIndex** is greater than 0 and moves focus in ascending or descending order.
Take the example provided by [defaultFocus](#setting-default-focus) as an example. The default order for sequential focus navigation is as follows:
With the example provided in [Setting Default Focus](#setting-default-focus), the default order for sequential focus navigation is as follows:
![en-us_image_0000001511421364](figures/en-us_image_0000001511421364.gif)
......
# Touchscreen Event
A touchscreen event refer to a callback event triggered when a finger or stylus is pressed, slides, or is lifted from a component. Touchscreen events include the [click event](#click-event), [drag event](#drag-event), and [touch event](#touch-event).
Touchscreen events are events triggered when a finger or stylus is placed on, moved along, or lifted from a component. They can be classified as [click event](#click-event), [drag event](#drag-event), or [touch event](#touch-event).
**Figure 1** Touchscreen event principles
......@@ -12,19 +12,14 @@ A touchscreen event refer to a callback event triggered when a finger or stylus
## Click Event
A click event refers to a complete press and lift action performed by using a finger or a stylus. When a click event occurs, the following callback is triggered:
A click event is triggered when a complete press and lift action performed by using a finger or a stylus. When a click event occurs, the following callback is triggered:
```ts
onClick(event: (event?: ClickEvent) => void)
```
The **event** parameter provides the coordinates of the click event relative to the window or component and the event source where the click occurs.
For example, the click event of a button is used to control the display and hiding of an image.
The **event** parameter provides the coordinates of the click relative to the window or component as well as the event source where the click occurs, for example, a button, a click on which shows or hides an image.
```ts
@Entry
......@@ -42,7 +37,7 @@ struct IfElseTransition {
} else {
this.btnMsg = 'show';
}
// Click the button to control the display and hiding of the image.
// Click the button to show or hide the image.
this.flag = !this.flag;
})
if (this.flag) {
......@@ -56,7 +51,7 @@ struct IfElseTransition {
## Drag Event
A drag event is triggered when a user presses and holds a component (&gt;=500 ms) using a finger or stylus and drags the component to the drop target. The process of triggering a drag event is as follows:
A drag event is triggered when a user long presses a component (&gt;=500 ms) using a finger or stylus and drags the component to the drop target. The following figure illustrates the process of triggering a drag event.
![en-us_image_0000001562820825](figures/en-us_image_0000001562820825.png)
......@@ -70,11 +65,11 @@ The drag event provides the following [APIs](../reference/arkui-ts/ts-universal-
| API | Description |
| ---------------------------------------- | ---------------------------------------- |
| onDragStart(event:&nbsp;(event?:&nbsp;DragEvent,&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;CustomBuilder&nbsp;\|&nbsp;DragItemInfo) | Triggered when dragging starts. Currently, only custom **pixelmap** objects and custom components are supported. |
| onDragEnter(event:&nbsp;(event?:&nbsp;DragEvent,&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | Triggered when the dragged item enters a valid drop target. **DragEvent** indicates the position where the drag occurs. **extraParmas** indicates the additional information about the drag event.|
| onDragLeave(event:&nbsp;(event?:&nbsp;DragEvent,&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | Triggered when the dragged item leaves a valid drop target. **DragEvent** indicates the position where the drag occurs. **extraParmas** indicates the additional information about the drag event.|
| onDragMove(event:&nbsp;(event?:&nbsp;DragEvent,&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | Triggered when the dragged item moves in a valid drop target. **DragEvent** indicates the position where the drag occurs. **extraParmas** indicates the additional information about the drag event.|
| onDrop(event:&nbsp;(event?:&nbsp;DragEvent,&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | Triggered when the dragged item is dropped on a valid drop target. **DragEvent** indicates the position where the drag occurs. **extraParmas** indicates the additional information about the drag event.|
| onDragStart(event: (event?: DragEvent, extraParams?: string) =&gt; CustomBuilder \| DragItemInfo) | Triggered when dragging starts. Currently, only custom **pixelmap** objects and custom components are supported. |
| onDragEnter(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item enters a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDragLeave(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item leaves a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDragMove(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item moves in a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDrop(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item is dropped on a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
The following is an example of dragging a component out of a window in cross-window dragging:
......@@ -87,11 +82,7 @@ import image from '@ohos.multimedia.image';
@Entry
@Component
struct Index {
@State text: string = ''
@State bool1: boolean = false
@State bool2: boolean = false
@State visible: Visibility = Visibility.Visible
@State pixelMap: PixelMap = undefined
private pixelMapReader = undefined
aboutToAppear() {
......@@ -115,7 +106,6 @@ struct Index {
const promise = image.createPixelMap(color, opts);
promise.then((data) => {
console.info('create pixmap has info message: ' + JSON.stringify(data))
this.pixelMap = data;
this.pixelMapReader = data;
})
}
......@@ -151,8 +141,6 @@ struct Index {
.visibility(this.visible)
.onDragStart(() => { // Triggered when cross-window dragging starts.
console.info('Text onDrag start')
this.bool1 = true
this.text = 'TextDrag'
return { pixelMap: this.pixelMapReader, extraInfo: 'custom extra info.' }
})
.onDrop((event: DragEvent, extraParams: string) => {
......@@ -247,20 +235,20 @@ struct Index {
## Touch Event
When a finger or stylus touches a component, a touch event corresponding to the action is triggered, such as a press (Down), slide (Move), or lift (Up) event.
A touch event is triggered when a finger or stylus is placed on, moved along, or lifted from a component.
```ts
onTouch(event: (event?: TouchEvent) => void)
```
- If **event.type** is **TouchType.Down**, the finger or stylus is pressed.
- If **event.type** is **TouchType.Down**, the finger or stylus is placed on the component.
- If** event.type** is **TouchType.Up**, the finger or stylus is lifted.
- If **event.type** is **TouchType.Up**, the finger or stylus is lifted from the component.
- If **event.type** is **TouchType.Move**, the finger or stylus is pressed and moved.
- If **event.type** is **TouchType.Move**, the finger or stylus is moved along the component.
The touch event may be triggered by multiple fingers at the same time. Information such as the location of the finger that triggers the event, unique identifier of the finger, finger information changed, and an input device source may be obtained by using the **event** parameter.
The touch event supports single and multi-touch interactions. Information about the touch event can be obtained using the **event** parameter, such as the location of the finger that triggers the event, unique identifier of the finger, finger information changed, and the input device source.
```ts
......
......@@ -8,13 +8,13 @@ The drawing components are used to draw graphs on the page. The **\<Shape>** com
A drawing component can be created in either of the following ways:
- Drawing components use **\<Shape>** as their parent to implement the effect similar to SVG. The API is called in the following format:
- Create a drawing component with **\<Shape>** as their parent to implement the effect similar to SVG. The API used is as follows:
```ts
Shape(value?: PixelMap)
```
Create a drawing component with a parent component. The **value** parameter is used to set the drawing target. You can draw a graph in the specified **PixelMap** object. If the **value** parameter is not set, the graph is drawn in the current drawing target.
In the API, the **value** parameter sets the drawing target. You can draw a graph in the specified **PixelMap** object. If the **value** parameter is not set, the graph is drawn in the current drawing target.
```ts
Shape() {
......@@ -23,13 +23,13 @@ A drawing component can be created in either of the following ways:
```
- The **\<Shape>** component is used independently to draw a specific shape. Seven shapes are supported: [Circle](../reference/arkui-ts/ts-drawing-components-circle.md), [Ellipse](../reference/arkui-ts/ts-drawing-components-ellipse.md), [Line](../reference/arkui-ts/ts-drawing-components-line.md), [Polyine](../reference/arkui-ts/ts-drawing-components-polyline.md), [Polygon](../reference/arkui-ts/ts-drawing-components-polygon.md), [Path](../reference/arkui-ts/ts-drawing-components-path.md), and [Rect](../reference/arkui-ts/ts-drawing-components-rect.md). The following uses the **Circle** API as an example:
- Create an independent drawing component to draw a specific shape. Seven shapes are supported: [Circle](../reference/arkui-ts/ts-drawing-components-circle.md), [Ellipse](../reference/arkui-ts/ts-drawing-components-ellipse.md), [Line](../reference/arkui-ts/ts-drawing-components-line.md), [Polyine](../reference/arkui-ts/ts-drawing-components-polyline.md), [Polygon](../reference/arkui-ts/ts-drawing-components-polygon.md), [Path](../reference/arkui-ts/ts-drawing-components-path.md), and [Rect](../reference/arkui-ts/ts-drawing-components-rect.md). The following uses the **Circle** API as an example:
```ts
Circle(options?: {width?: string | number, height?: string | number}
```
Draws a circle on a page. The **width** parameter indicates the width of the circle, and the **height** parameter indicates the height of the circle. The diameter of the circle is determined by the minimum width and height.
This API draws a circle on a page. The **width** parameter indicates the width of the circle, and the **height** parameter indicates the height of the circle. The diameter of the circle is determined by the minimum width and height.
```ts
Circle({ width: 150, height: 150 })
......@@ -101,7 +101,7 @@ The following three examples describe how to use the viewport:
.backgroundColor("#F5DC62")
```
![viewport (2) ](figures/viewport (2) .jpg)
![viewport-2](figures/viewport-2.jpg)
- Create a shape component whose width and height are both 300, with a yellow background and a viewport whose width and height are both 300. Fill the viewport with a blue rectangle, draw a circle with a radius of 75 in the viewport, and move the viewport 150 to the right and below respectively.
......@@ -117,7 +117,7 @@ The following three examples describe how to use the viewport:
```
![viewport (3) ](figures/viewport (3) .jpg)
![viewport-3](figures/viewport-3.jpg)
## Setting Styles
......
# Gesture Binding
Different gesture events are bound to each component and the event response mode is designed. When gesture recognition is successful, the ArkUI framework notifies the component of the gesture recognition result through event callback.
You can bind to each component different gesture events and design the logic for responding to these events. When a gesture is successfully recognized, the ArkUI framework notifies the component of the gesture recognition result through event callback.
## gesture (Common Gesture Binding Method)
......@@ -11,9 +11,9 @@ Different gesture events are bound to each component and the event response mode
.gesture(gesture: GestureType, mask?: GestureMask)
```
Binds a gesture to the specified component. **gesture** is a general gesture binding method.
**gesture** is a frequently used API for binding a gesture to a component.
For example, the tap gesture TapGesture can be bound to the **\<Text>** component by using the **gesture** method.
For example, you can use it to bind the tap gesture to the **\<Text>** component.
```ts
......@@ -24,7 +24,7 @@ struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
// Use the gesture method to bind the TapGesture.
// Use the gesture API to bind the tap gesture.
.gesture(
TapGesture()
.onAction(() => {
......@@ -45,11 +45,11 @@ struct Index {
.priorityGesture(gesture: GestureType, mask?: GestureMask)
```
Binds gestures that are preferentially recognized to a component.
The **priorityGesture** API binds gestures that are preferentially recognized to a component.
By default, when a parent component and a child component use gesture to bind gestures of the same type, the child component preferentially identifies gestures bound by using gesture. When the parent component uses priorityGesture to bind gestures of the same type as the child component, the parent component preferentially identifies gestures bound through priorityGesture.
By default, the child component preferentially recognizes the gesture specified by **gesture**, and the parent component preferentially recognizes the gesture specified by **priorityGesture** (if set).
For example, when the parent component Column and child component Text are bound to the TapGesture gesture at the same time, and the parent component is bound in the form of a priority gesture priorityGesture, the TapGesture bound to the parent component is preferentially responded.
In the following example, the parent component **\<Column>** and child component **\<Text>** are both bound to the tap gesture. As the **\<Column>** is bound to the gesture through **priorityGesture**, the tap gesture recognized by the parent component is preferentially responded to.
......@@ -69,7 +69,7 @@ struct Index {
}
.height(200)
.width(250)
// When this parameter is set to priorityGesture, the TapGesture gesture event of the Text component is ignored when the text area is tapped, and the TapGesture gesture event of the parent component Column is preferentially responded.
// When the tap gesture is bound to the parent <Column> component through priorityGesture, the tap gesture event of the <Text> component is ignored when the text area is tapped, and the tap gesture event of the<Column> component is preferentially responded to.
.priorityGesture(
TapGesture()
.onAction(() => {
......@@ -87,9 +87,9 @@ struct Index {
.parallelGesture(gesture: GestureType, mask?: GestureMask)
```
Binds the same gesture that can be responded to at the same time to the parent and child components.
The **parallelGesture** API binds to a component the gesture that can be triggered together with the child component gesture.
By default, the gesture event does not bubble up. When a parent component and a child component are bound to a same gesture, the gesture events bound to the parent component and the child component compete with each other, and a gesture event of at most one component can be responded to. When the parent component is bound to parallel gesture parallelGesture, the same gesture events of the parent and child components can be triggered to implement a bubbling effect.
By default, the gesture event does not bubble up. When a parent component and a child component are bound to a same gesture, the gesture events bound to the parent component and the child component compete with each other, and a gesture event of at most one component can be responded to. When **parallelGesture** is set, the same gesture events can be triggered for the parent and child components, thereby implementing a bubbling effect.
......@@ -109,7 +109,7 @@ struct Index {
}
.height(200)
.width(250)
// If this parameter is set to parallelGesture, the TapGesture gesture events of the parent component Column and child component Text are responded when the text area is clicked.
// When parallelGesture is set, the tap gestures on the <Column> component and on the child <Text> component are both recognized.
.parallelGesture(
TapGesture()
.onAction(() => {
......@@ -122,4 +122,4 @@ struct Index {
>**NOTE**
>
>When the parent component and the child component are bound to both the click gesture event and the double-click gesture event, both the parent component and the child component respond only to the click gesture event.
>When the parent component and the child component are bound to both the click gesture and the double-click gesture, both the parent component and the child component respond only to the click gesture.
......@@ -10,18 +10,18 @@ GestureGroup(mode:GestureMode, ...gesture:GestureType[])
```
- **mode**: declare a type of the combined gesture. This parameter is mandatory and belongs to the GestureMode enumeration class.
- **mode**: recognition mode of combined gestures. This parameter is mandatory and belongs to the **GestureMode** enumeration class.
- **gesture**: array consisting of multiple gestures. This parameter is mandatory. .
## Continuous Recognition
For continuous recognition, **GestureMode** corresponding to the combined gesture is **Sequence**. Continuous recognition of combined gestures will recognize gestures according to the registration sequence of gestures until all gestures are recognized successfully. When one gesture in the continuously recognized combined gestures fails to be recognized, all gestures fail to be recognized.
For continuous recognition, the value of **GestureMode** is **Sequence**. In this gesture mode, gestures registered in the combined gestures will be recognized according to the registration sequence until they are all recognized successfully. If any of the registered gestures fails to be recognized, all gestures fail to be recognized.
A continuous gesture formed by combining a touch-and-hold gesture and a drag gesture is used as an example.
In the following example, the combined gestures for continuous recognition are the long press gesture and pan gesture.
The translate attribute is bound to a Column component. You can modify the attribute to move the component. Then, bind the sequence gesture combined by LongPressGesture and PanGesture to the component. When LongPressGesture is triggered, the displayed number is updated. When a user drags a widget after touching and holding the widget, the widget is dragged based on the callback function of the drag gesture.
The **translate** attribute is bound to a **\<Column>** component. You can set the attribute to translate the component. Then, bind **LongPressGesture** and **PanGesture** to the component in the **Sequence** gesture mode. When a long press gesture is recognized, the displayed number is updated. When the user drags the component after the long press gesture, the component is dragged based on the callback function of the pan gesture.
......@@ -42,17 +42,17 @@ struct Index {
Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
.fontSize(28)
}
//Bind the translate attribute to move the component.
// Bind the translate attribute to translate the component.
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.height(250)
.width(300)
// The following combined gestures are identified in sequence. When the touch and hold gesture event is not triggered normally, the drag gesture event is not triggered.
// The following combined gestures are recognized in sequence. When the long press gesture event is not triggered correctly, the pan gesture event is not triggered.
.gesture(
// Declare that the type of the combined gesture is the Sequence type.
// Set the gesture mode to Sequence.
GestureGroup(GestureMode.Sequence,
// The first gesture triggered by the combined gesture is a touch-and-hold gesture, and the touch-and-hold gesture can be responded to for multiple times.
// The first gesture recognized in the combined gestures is the long press gesture, which can be responded to for multiple times.
LongPressGesture({ repeat: true })
// Increase the count displayed on the Text component when the touch and hold gesture is successfully recognized.
// When the long press gesture is successfully recognized, the value of count displayed on the <Text> component is increased.
.onAction((event: GestureEvent) => {
if (event.repeat) {
this.count++;
......@@ -62,13 +62,13 @@ struct Index {
.onActionEnd(() => {
console.info('LongPress end');
}),
// The PanGesture gesture is triggered when you drag the slider after touching and holding the slider.
// The pan gesture is triggered when the component is dragged after the long press gesture is recognized.
PanGesture()
.onActionStart(() => {
this.borderStyles = BorderStyle.Dashed;
console.info('pan start');
})
// When the gesture is triggered, the dragging distance is obtained according to the callback, and the displacement distance of the component is modified to move the component.
// When the gesture is triggered, the pan distance is obtained based on the callback, and the displacement distance of the component is modified. In this way, the component is translated.
.onActionUpdate((event: GestureEvent) => {
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
......@@ -91,14 +91,14 @@ struct Index {
>**NOTE**
>
>The drag event is a typical continuous recognition combined gesture event, and is formed by combining a touch and hold gesture event and a slide gesture event. The drag event is triggered only when the user touches and holds the gesture for a preset period of time. If the touch and hold event is not reached or the slider is not performed after the touch and hold event, the drag event fails to be identified.
>The drag event is a typical use case of continuous recognition with the long press gesture and pan gesture combined. It is triggered only when the user performs the pan gesture within the preset time frame after a long press gesture is recognized. If the long press gesture is not recognized or the pan gesture is not performed within the preset time frame, the drag event will not be triggered.
## Parallel Recognition
For parallel recognition, **GestureMode** corresponding to the combined gesture is **Parallel**. Parallel recognition of gestures registered in the combined gestures will be recognized at the same time until all gestures are recognized. The gestures in the gesture combination are recognized in parallel without affecting each other.
For parallel recognition, the value of **GestureMode** is **Parallel**. In this gesture mode, gestures registered in the combined gestures will be recognized at the same time until they are all recognized successfully. The gestures are recognized in parallel without affecting each other.
For example, a parallel recognition gesture formed by a tap gesture and a double-tap gesture is bound to a Column component. Because the tap gesture and the double-tap gesture are recognized in parallel, the two gestures may be recognized at the same time, and the two gestures do not interfere with each other.
For example, if the tap gesture and the double-tap gesture are bound to the \**<Column>** component in parallel recognition mode, they can be recognized at the same time, and the recognition of these two gestures does not interfere with each other.
......@@ -117,7 +117,7 @@ struct Index {
}
.height(200)
.width(250)
// The following combined gestures are parallel. After the tap gesture is recognized successfully, if you tap the gesture again within the specified time, the double-tap gesture will also be recognized successfully.
// The following combined gestures are recognized in parallel mode. After a tap gesture is recognized successfully, if another tap gesture is recognized within the specified time frame, a double-tap gesture will also be recognized.
.gesture(
GestureGroup(GestureMode.Parallel,
TapGesture({ count: 1 })
......@@ -140,20 +140,20 @@ struct Index {
>**NOTE**
>
>After a tap gesture and a double-tap gesture form a parallel recognition combined gesture, when a tap is performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
>After a tap gesture and a double-tap gesture are combined for parallel recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
>
>When there is only a single tap, the tap gesture is recognized successfully, but the double-tap gesture fails to be recognized.
>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
>
>When there are two clicks, if the interval between the two clicks is within a specified period (300 ms by default), two click events and one double-click event are triggered.
>When there are two taps and the interval between the two taps is within a specified period (300 ms by default), two tap events and one double-tap event are triggered.
>
>When there are two clicks, if the interval between the two clicks exceeds the specified time, the two clicks are triggered but the double-click event is not triggered.
>When there are two taps, but the interval between the two taps exceeds the specified time, two tap events are triggered but the double-tap event is not triggered.
## Exclusive Recognition
For exclusive recognition, **GestureMode** corresponding to the combined gesture is **Exclusive**. The gestures registered in the mutually exclusive recognition combination gesture are recognized at the same time. If one gesture is recognized successfully, the gesture recognition ends, and all other gestures fail to be recognized.
For exclusive recognition, the value of **GestureMode** is **Exclusive**. In this gesture mode, gestures registered in the combined gesture are recognized at the same time. If one gesture is recognized successfully, the gesture recognition ends, and all other gestures fail to be recognized.
A mutually exclusive recognition combination gesture formed by binding a click gesture and a double-tap gesture to a Column component is used as an example. Because a click gesture can be triggered only once and a double-tap gesture needs to be triggered twice, each click event is consumed by the click gesture and cannot be accumulated into a double-tap gesture, the double-tap gesture cannot be triggered.
For example, if the tap gesture and the double-tap gesture are bound to the \**<Column>** component in exclusive recognition mode, only a tap gesture event can be triggered. This is because a tap gesture requires a single tap to be triggered, and a double-tap gesture event requires two taps to be triggered; each tap event is consumed by the tap gesture and cannot be accumulated into a double-tap gesture.
......@@ -172,7 +172,7 @@ struct Index {
}
.height(200)
.width(250)
//The following combined gestures are mutually exclusive. After the tap gesture is recognized successfully, the double-tap gesture fails to be recognized.
// The following combined gestures are mutually exclusive. After the tap gesture is recognized successfully, the double-tap gesture fails to be recognized.
.gesture(
GestureGroup(GestureMode.Exclusive,
TapGesture({ count: 1 })
......@@ -195,8 +195,8 @@ struct Index {
>**NOTE**
>
>After the tapping gesture and the double-tap gesture form a mutually exclusive recognition combination gesture, when tapping is performed in the area, the tapping gesture and the double-tap gesture are recognized at the same time.
>After a tap gesture and a double-tap gesture are combined for exclusive recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
>
>When there is only a single tap, the tap gesture is recognized successfully, but the double-tap gesture fails to be recognized.
>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
>
>When there are two taps, the tap gesture declares that the recognition is successful when the tap gesture is tapped for the first time. In this case, the double-tap gesture has failed. Even if the second tap is performed within the specified time, the double-tap gesture event is not responded. In this case, the second recognition success of the tap gesture event is triggered.
>When there are two taps, the gesture recognition is declared as successful when the first tap gesture is recognized. In this case, the double-tap gesture fails to be recognized. Even if the second tap is performed within the specified time, the double-tap gesture event is not responded to. Instead, another tap gesture event is triggered.
......@@ -9,13 +9,13 @@ TapGesture(value?:{count?:number; fingers?:number})
```
Tap gestures support single tap and multiple taps. There are two optional parameters:
Triggers a tap gesture with one or more taps. This API has two optional parameters:
- **count**: number of consecutive taps recognized by the tap gesture. This parameter is optional. The default value is 1. If this parameter is set to an invalid value less than 1, the default value is used. If multiple clicks are configured, the timeout interval for the previous lift and next press is 300 ms.
- **count**: number of consecutive taps required for gesture recognition. The default value is 1. A value less than 1 evaluates to the default value **1**. If multi-tap is configured, the timeout interval between a lift and the next tap is 300 ms.
- **fingers**: number of fingers that trigger the touch. The minimum value is 1, and the maximum value is 10. The default value is 1. This parameter is optional. When multi-finger is configured, if the number of fingers used for tap does not reach the specified number within 300 ms after the first finger is tapped, the gesture fails to be recognized. Gesture recognition fails if the number of fingers used for tap exceeds the configured number.
For example, to bind a double-tap gesture (a tap gesture whose count value is 2) to the Text component, run the following command:
- **fingers**: number of fingers required for gesture recognition. The value ranges from 1 to 10. The default value is **1**. If the number of fingers used for the tap is less than the specified one within 300 ms after the first finger is tapped, the gesture fails to be recognized. Gesture recognition also fails if the number of fingers used for the tap exceeds the value of **fingers**.
The following example binds a double-tap gesture (a tap gesture whose **count** value is **2**) to the **\<Text>** component:
```ts
// xxx.ets
......@@ -28,7 +28,7 @@ Tap gestures support single tap and multiple taps. There are two optional parame
Column() {
Text('Click twice').fontSize(28)
.gesture(
//Bind the TapGesture whose count is 2.
// Bind a tap gesture whose count value is 2.
TapGesture({ count: 2 })
.onAction((event: GestureEvent) => {
this.value = JSON.stringify(event.fingerList[0]);
......@@ -55,17 +55,17 @@ LongPressGesture(value?:{fingers?:number; repeat?:boolean; duration?:number})
```
The touch-and-hold gesture is used to trigger a touch-and-hold gesture event. The minimum quantity of fingers that trigger the touch-and-hold gesture is 1, the minimum touch-and-hold event is 500 milliseconds, and has three optional parameters:
Triggers a long press gesture, which requires one or more fingers with a minimum 500 ms hold-down time. This API has three optional parameters:
- **fingers**: minimum number of fingers required to trigger the touch and hold gesture. The minimum value is 1 and the maximum value is 10. The default value is 1. This parameter is optional.
- **fingers**: minimum number of fingers required for gesture recognition. The value ranges from 1 to 10. The default value is **1**.
- **repeat**: whether to continuously trigger event callback. The default value is false. This parameter is optional.
- **repeat**: whether to continuously trigger the event callback. The default value is **false**.
- **duration**: minimum duration (in milliseconds) required for triggering a long press. The default value is 500. This parameter is optional.
- **duration**: minimum hold-down time, in ms. The default value is **500**.
The following describes how to bind a touch and hold gesture that can be repeatedly triggered to the Text component:
The following exemplifies how to bind a long press gesture that can be repeatedly triggered to the **\<Text>** component:
......@@ -80,7 +80,7 @@ struct Index {
Column() {
Text('LongPress OnAction:' + this.count).fontSize(28)
.gesture(
// Bind the LongPressGesture that can be triggered repeatedly.
// Bind the long press gesture that can be triggered repeatedly.
LongPressGesture({ repeat: true })
.onAction((event: GestureEvent) => {
if (event.repeat) {
......@@ -113,17 +113,17 @@ PanGestureOptions(value?:{ fingers?:number; direction?:PanDirection; distance?:n
```
Drag gestures are used to trigger drag gesture events. When the sliding distance reaches the minimum sliding distance (5vp by default), drag gestures are successfully identified. There are three optional parameters:
Triggers a pan gesture, which requires the minimum movement distance (5 vp by default) of a finger on the screen. This API has three optional parameters:
- **fingers**: minimum number of fingers required to trigger a drag gesture. This parameter is optional. The minimum value is 1 and the maximum value is 10. The default value is 1.
- **fingers**: minimum number of fingers required for gesture recognition. The value ranges from 1 to 10. The default value is **1**.
- **direction**: direction of the gesture that triggers the drag. This parameter is optional. The enumerated values support the AND and OR operations. The default value is **Pandirection.All.**
- **direction**: pan direction. The enumerated value supports the AND (&amp;) and OR (\|) operations. The default value is **Pandirection.All.**
- **distance**: specifies the minimum drag recognition distance for triggering drag. This parameter is optional. The unit is vp. The default value is 5.
- **distance**: minimum pan distance required for gesture recognition, in vp. The default value is **5**.
Binding a drag gesture to a Text component is used as an example. You can drag a component by modifying the layout position information of the component in the callback function of the drag gesture.
The following exemplifies how to bind a pan gesture to the **\<Text>** component. You can pan a component by modifying the layout and position information of the component in the **PanGesture** callback.
......@@ -145,15 +145,15 @@ struct Index {
.width(300)
.padding(20)
.border({ width: 3 })
//Bind the layout position information to the component.
// Bind the layout and position information to the component.
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.gesture(
//Bind drag gestures.
// Bind the pan gesture to the component.
PanGesture()
.onActionStart((event: GestureEvent) => {
console.info('Pan start');
})
//When the drag gesture is triggered, modify the layout position information of the component based on the callback function.
// When the drag gesture is triggered, modify the layout and position information of the component based on the callback.
.onActionUpdate((event: GestureEvent) => {
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
......@@ -176,9 +176,9 @@ struct Index {
>**NOTE**
>
>Most sliding components, such as List, Grid, Scroll, and Tab, slide through PanGesture. Bind [Drag gesture (PanGesture)] (#Drag gesture pangesture) to subcomponents in the components. [SwipeGesture](#SwipeGesture swipegesture) will cause gesture competition.
>Most slidable components, such as **\<List>**, **\<Grid>**, **\<Scroll>**, and **\<Tab>**, slide through the pan gesture. Therefore, binding the [pan gesture](#pangesture) or [swipe gesture](#swipegesture) to child components will cause gesture competition.
>
>When a subcomponent is bound to PanGesture, sliding in the subcomponent area triggers only PanGesture of the subcomponent. If the parent component needs to respond, you need to modify the gesture binding method or transfer messages from the child component to the parent component, or modify the PanGesture parameter distance of the parent and child components to make the dragging more sensitive. When a subcomponent is bound to SwipeGesture, you need to modify the parameters of PanGesture and SwipeGesture to achieve the required effect because the triggering conditions of PanGesture and SwipeGesture are different.
>When a child component is bound to the pan gesture, sliding in the child component area triggers only the pan gesture of the child component. If the parent component needs to respond, you need to modify the gesture binding method or transfer messages from the child component to the parent component, or modify the **PanGesture** parameter distance of the parent and child components to make the panning more sensitive. When a child component is bound to the swipe gesture, you need to modify the parameters of **PanGesture** and **SwipeGesture** to achieve the required effect because the triggering conditions of **PanGesture** and **SwipeGesture** are different.
## PinchGesture
......@@ -323,11 +323,11 @@ SwipeGesture(value?:{fingers?:number; direction?:SwipeDirection; speed?:number})
Swipe gestures are used to trigger swipe events. A swipe gesture is recognized when the swipe speed is 100 vp/s or higher. There are three optional parameters:
- **fingers**: minimum number of fingers required to trigger a swipe gesture. This parameter is optional. The minimum value is 1 and the maximum value is 10. The default value is 1.
- **fingers**: minimum number of fingers required to trigger a swipe gesture. TThe minimum value is 1 and the maximum value is 10. The default value is 1.
- **direction**: Swipe direction. This parameter is optional. The enumerated values support the AND and OR operations. The default value is **SwipeDirection.All**.
- **direction**: swipe direction. The enumerated values support the AND and OR operations. The default value is **SwipeDirection.All**.
- **speed**: minimum speed of the swipe gesture, in vp/s.This parameter is optional. The default value is 100.
- **speed**: minimum speed of the swipe gesture, in vp/s. The default value is **100**.
The following describes how to bind a sliding gesture to the Column component to rotate the component:
......@@ -357,7 +357,7 @@ struct Index {
.gesture(
// Bind the sliding gesture and restrict it to be triggered only when the user slides in the vertical direction.
SwipeGesture({ direction: SwipeDirection.Vertical })
//When the sliding gesture is triggered, obtain the sliding speed and angle to modify the layout parameters of the component.
// When the swipe gesture is triggered, the swipe speed and angle are obtained, which can be used to modify the layout parameters.
.onAction((event: GestureEvent) => {
this.speed = event.speed;
this.rotateAngle = event.angle;
......
......@@ -12,7 +12,8 @@ ArkUI provides the \<[Grid](../reference/arkui-ts/ts-container-grid.md)> contain
Each item in the **\<Grid>** container corresponds to a **\<GridItem>** component, as shown below.
**Figure 1** Relationship between \<Grid> and \<GridItem> components
**Figure 1** Relationship between \<Grid> and \<GridItem> components
![en-us_image_0000001511900472](figures/en-us_image_0000001511900472.png)
>**NOTE**
......@@ -21,7 +22,8 @@ Each item in the **\<Grid>** container corresponds to a **\<GridItem>** componen
The grid layout is a two-dimensional layout. The **\<Grid>** component allows you to define the number of rows and columns, proportion of each row and column, number of rows or columns that child components span, and the horizontal and vertical alignment. When the **\<Grid>** container size changes, the child components and spacing are adjusted proportionally. By leveraging these layout capabilities, you can build grid layouts of different styles, as shown below.
**Figure 2** Grid layout
**Figure 2** Grid layout
![en-us_image_0000001562700473](figures/en-us_image_0000001562700473.png)
The size of the **\<Grid>** component follows its width and height settings (if configured) or adapts to the size of its parent component.
......@@ -48,7 +50,8 @@ You can set the number and proportion of rows and columns to determine the overa
The values of **rowsTemplate** and **columnsTemplate** are a string consisting of 'number+fr' segments, separated by spaces. Wherein **frs** indicates the number of rows or columns in the grid layout, and the number before **fr** is used to calculate the proportion of the row or column in the grid width, thereby determining the width of the row or column.
**Figure 3** Example of the proportion of rows and columns
**Figure 3** Example of the proportion of rows and columns
![en-us_image_0000001562820833](figures/en-us_image_0000001562820833.png)
The preceding figure shows a grid layout with three rows and three columns. The grid layout is divided into three parts in the vertical direction with each row taking up 1/3, and four parts in the horizontal direction with the first column taking up 1/4, the second column 2/4, and the third column 1/4.
......@@ -79,7 +82,7 @@ In real-world applications, an uneven grid layout, where grid cells span a varyi
A common application with an uneven grid layout is the calculator. As shown in the following figure, the **0** key spans the first and second columns, and the **=** key spans the fifth and sixth rows. For a grid layout created using the **\<Grid>** component, the row and column numbers start from 1 and increase continuously.
**Figure 5** Calculator
**Figure 5** Calculator
![en-us_image_0000001511421292](figures/en-us_image_0000001511421292.png)
......@@ -114,7 +117,7 @@ GridItem() {
When neither the number nor proportion is set for rows and columns in a grid layout, you can use the **layoutDirection** attribute to set the main axis direction and thereby specify the arrangement mode of child components. In addition, you can use the **minCount** and **maxCount** attributes to restrict the number of grid cells along the main axis.
**Figure 6** Main axis direction
**Figure 6** Main axis direction
![en-us_image_0000001562700469](figures/en-us_image_0000001562700469.png)
......@@ -140,7 +143,7 @@ Grid() {
The grid layout organizes its internal elements in two-dimensional layout mode, as shown in the following figure.
**Figure 7** General office services
**Figure 7** General office services
![en-us_image_0000001563060729](figures/en-us_image_0000001563060729.png)
......@@ -206,7 +209,7 @@ struct OfficeService {
The horizontal spacing between two grid cells is called row spacing, and the vertical spacing is called column spacing, as shown in the following figure.
**Figure 8** Row spacing and column spacing
**Figure 8** Row spacing and column spacing
![en-us_image_0000001511580908](figures/en-us_image_0000001511580908.png)
......@@ -315,7 +318,7 @@ For details about the implementation, see the example in [LazyForEach: Lazy Data
When the grid is rendered in lazy loading mode, to improve the grid scrolling experience and minimize white blocks during grid scrolling, you can use the **cachedCount** parameter of the **\<Grid>** component. This parameter sets the number of grid items preloaded outside of the screen and is valid only in **LazyForEach**.
Specifically, the number of the grid items to cache before and after the currently displayed one equals the value of **cachedCount** multiplied by the number of columns. Grid items that exceed the display and cache range are released.
Specifically, the number of the grid items to cache before and after the currently displayed one equals the value of **cachedCount** multiplied by the number of columns. Grid items that exceed the display and cache range are released.
```ts
Grid() {
......@@ -328,12 +331,7 @@ Grid() {
.cachedCount(3)
```
>**NOTE**
>
>A greater **cachedCount** value may result in higher CPU and memory overhead of the UI. Adjust the value by taking into account both the comprehensive performance and user experience.
##
-
> **NOTE**
>
> A greater **cachedCount** value may result in higher CPU and memory overhead of the UI. Adjust the value by taking into account both the comprehensive performance and user experience.
<!--no_check-->
\ No newline at end of file
......@@ -51,7 +51,7 @@ The media query condition consists of the media type (optional), logical operato
### Syntax
Syntax rules include [media-type](#media-type), [media-logic-operations](#media-logic-operations), and [media-feature]. (#media-feature).
Syntax rules include [media-type](#media-type), [media-logic-operations](#media-logic-operations), and [media-feature](#media-feature).
```ts
......@@ -84,11 +84,11 @@ You can use logical operators (**and**, **or**, **not**, and **only**) to compos
| Type | Description |
| -------------- | ---------------------------------------- |
| and | The **and** operator is used to combine multiple media features into one media query, in a logical AND operation. The query is valid only when all media features are true. It can also combine media types and media functions. For example, **screen&nbsp;and&nbsp;(device-type:&nbsp;wearable)&nbsp;and&nbsp;(max-height:&nbsp;600)** evaluates to **true** when the device type is wearable and the maximum height of the application is 600 pixel units.|
| and | The **and** operator is used to combine multiple media features into one media query, in a logical AND operation. The query is valid only when all media features are true. It can also combine media types and media functions. For example, **screen and (device-type: wearable) and (max-height: 600)** evaluates to **true** when the device type is wearable and the maximum height of the application is 600 pixel units.|
| or | The **or** operator is used to combine multiple media features into one media query, in a logical OR operation. The query is valid if a media feature is true. For example, **screen and (max-height: 1000) or (round-screen: true)** indicates that the query is valid when the maximum height of the application is 1000 pixel units or the device screen is round.|
| not | The **not** operator is used to perform a logical negation for a media query. **true** is returned if the query condition is not met. Otherwise, **false** is returned. For example, **not&nbsp;screen&nbsp;and&nbsp;(min-height:&nbsp;50)&nbsp;and&nbsp;(max-height:&nbsp;600)** evaluates to **true** when the height of the application is less than 50 pixel units or greater than 600 pixel units.<br>You must specify the media type when using the **not** operator.|
| only | The **only** operator applies the selected style only when the entire expression is matched. It can be used to prevent ambiguity on browsers of earlier versions. The statements that contain both media types and media features produce ambiguity when they are received by some browsers of earlier versions. For example, regarding **screen&nbsp;and&nbsp;(min-height:&nbsp;50)**, the browsers of earlier versions would mislead this sentence into **screen**, causing the fact that the specified style is applied when only the media type is matched. In this case, the **only** operator can be used to avoid this issue.<br>You must specify the media type when using the **only** operator.|
| comma (,&nbsp;) | The **or** operator is used to combine multiple media features into one media query, in a logical OR operation. The query is valid if a media feature is true. The effect of a comma operator is equivalent to that of the **or** operator. For example, **screen and (min-height: 1000), (round-screen: true)** indicates that the query is valid when the minimum height of the application is 1000 pixel units or the device screen is round.|
| not | The **not** operator is used to perform a logical negation for a media query. **true** is returned if the query condition is not met. Otherwise, **false** is returned. For example, **not screen and (min-height: 50) and (max-height: 600)** evaluates to **true** when the height of the application is less than 50 pixel units or greater than 600 pixel units.<br>You must specify the media type when using the **not** operator.|
| only | The **only** operator applies the selected style only when the entire expression is matched. It can be used to prevent ambiguity on browsers of earlier versions. The statements that contain both media types and media features produce ambiguity when they are received by some browsers of earlier versions. For example, regarding **screen and (min-height: 50)**, the browsers of earlier versions would mislead this sentence into **screen**, causing the fact that the specified style is applied when only the media type is matched. In this case, the **only** operator can be used to avoid this issue.<br>You must specify the media type when using the **only** operator.|
| comma (, ) | The **or** operator is used to combine multiple media features into one media query, in a logical OR operation. The query is valid if a media feature is true. The effect of a comma operator is equivalent to that of the **or** operator. For example, **screen and (min-height: 1000), (round-screen: true)** indicates that the query is valid when the minimum height of the application is 1000 pixel units or the device screen is round.|
Media range operators include <=, >=, <, and >. For details, see the following table.
......@@ -110,12 +110,12 @@ The media features include the width and height of the application display area,
| Type | Description |
| ----------------- | ---------------------------------------- |
| height | Height of the drawing area of the application. |
| min-height | Minimum height of the drawing area of the application. |
| max-height | Maximum height of the drawing area of the application. |
| width | Width of the drawing area of the application. |
| min-width | Minimum width of the drawing area of the application. |
| max-width | Maximum width of the drawing area of the application. |
| height | Height of the drawing area of the application. |
| min-height | Minimum height of the drawing area of the application. |
| max-height | Maximum height of the drawing area of the application. |
| width | Width of the drawing area of the application. |
| min-width | Minimum width of the drawing area of the application. |
| max-width | Maximum width of the drawing area of the application. |
| resolution | Resolution of the device. The unit can be dpi, dppx, or dpcm. <br>- **dpi** indicates the number of physical pixels per inch. 1 dpi ≈ 0.39 dpcm.<br>- **dpcm** indicates the number of physical pixels per centimeter. 1 dpcm ≈ 2.54 dpi.<br>- **dppx** indicates the number of physical pixels in each pixel. (This unit is calculated based on this formula: 96 px = 1 inch, which is different from the calculation method of the px unit on the page.) 1 dppx = 96 dpi.|
| min-resolution | Minimum device resolution. |
| max-resolution | Maximum device resolution. |
......@@ -256,8 +256,3 @@ struct MediaQueryExample {
![landscape](figures/landscape.jpg)
##
......@@ -13,12 +13,15 @@ The **DisplayPriority** or **LayoutWeight** attribute of all child components is
- If the total main axis length of the child components is equal to the main axis length of the container in the first layout, no secondary layout is required.
![layout-performance-1](figures/layout-performance-1.png)
- If the total main axis length of the child components is less than the main axis length of the container in the first layout, the child components with valid **flexGrow** values will trigger secondary layout and be stretched to fill the container.
![layout-performace-2](figures/layout-performace-2.gif)
- If the total main axis length of the child components is greater than the main axis length of the container in the first layout, the child components with valid **flexShrink** (whose default value **1** is valid) values will trigger secondary layout and shrink to fill the container.
![layout-performace-3](figures/layout-performace-3.gif)
......@@ -31,9 +34,11 @@ In this scenario, the child components with the same **DisplayPriority** value a
- If the total main axis length of the child components is equal to the main axis length of the container in the first layout, no secondary layout is required.
![layout-performance-4](figures/layout-performance-4.png)
- If the total main axis length of the child components is less than the main axis length of the container in the first layout, the child components with valid **flexGrow** values will trigger secondary layout and be stretched to fill the container.
![layout-performace-5](figures/layout-performace-5.gif)
......@@ -48,6 +53,7 @@ The remaining space in the container is filled by child components for which the
- The child components are laid out only once in this process, and secondary layout is not triggered.
![layout-performace-6](figures/layout-performace-6.gif)
......
# Navigation
Generally, the [Navigation](../reference/arkui-ts/ts-basic-components-navigation.md) component functions as the root container of a page and supports three display modes: single page, column, and adaptive. In addition, Navigation provides properties to set the title bar, toolbar, and navigation bar of a page.
Generally, the [\<Navigation>](../reference/arkui-ts/ts-basic-components-navigation.md) component functions as the root container of a page and supports three display modes: single-page, column, and adaptive. In addition, **\<Navigation>** provides attributes to set the title bar, toolbar, and navigation bar of a page.
The pages of the Navigation component include the home page and content page. The home page consists of the title bar, content area, and toolbar. You can use the [NavRouter](../reference/arkui-ts/ts-basic-components-navrouter.md) child component in the content area to implement the navigation bar function. The content page displays the content of the [NavDestination](../reference/arkui-ts/ts-basic-components-navdestination.md) child component.
The pages of the Navigation component include the home page and content page. The home page consists of the title bar, content area, and toolbar. You can use the [\<NavRouter>](../reference/arkui-ts/ts-basic-components-navrouter.md) child component in the content area to implement the navigation bar function. The content page displays the content of the [\<NavDestination>](../reference/arkui-ts/ts-basic-components-navdestination.md) child component.
NavRouter is a special child component used together with Navigation. By default, NavRouter provides click response processing. Developers do not need to customize click event logic. NavRouter has only two root nodes. The second root node is NavDestination. NavDestination is a special child component used together with NavRouter to display the content page of the Navigation component. When a developer clicks the NavRouter component, the corresponding NavDestination content area is displayed.
**\<NavRouter>** is a special child component used together with **\<Navigation>**. It provides default processing logic for responding to clicks, eliminating the need for manual logic definition. **\<NavRouter>** has only two root nodes. The second root node is **\<NavDestination>**. **\<NavDestination>** is a special child component used together with **\<NavRouter>** to display the content page of the **\<Navigation>** component. When the user clicks the **\<NavRouter>** component, the corresponding **\<NavDestination>** content area is displayed.
## Setting the Page Display Mode
The Navigation component uses the mode attribute to set the page display mode.
The **\<Navigation>** component uses the **mode** attribute to set the page display mode.
- Adaptive Mode
By default, the Navigation component is in adaptive mode. In this case, the mode attribute is NavigationMode.Auto. In adaptive mode, when the device width is greater than 520 vp, the Navigation component uses the column mode. Otherwise, the Navigation component uses the single-page mode.
By default, the **\<Navigation>** component is in adaptive mode. In this case, the **mode** attribute is **NavigationMode.Auto**. In adaptive mode, when the device width is greater than 520 vp, the **\<Navigation>** component uses the column mode. Otherwise, the **\<Navigation>** component uses the single-page mode.
```
......@@ -27,11 +27,11 @@ The Navigation component uses the mode attribute to set the page display mode.
- Single-page mode
**Figure 1** Layout of a single page
**Figure 1** Single-page mode
![en-us_image_0000001511740532](figures/en-us_image_0000001511740532.png)
Set mode to NavigationMode.Stack so that the Navigation component can be displayed on a single page.
Set **mode** to **NavigationMode.Stack** so that the **\<Navigation>** component is displayed on a single page.
```ts
......@@ -41,15 +41,15 @@ The Navigation component uses the mode attribute to set the page display mode.
.mode(NavigationMode.Stack)
```
![Single Page 1] (figures /Single Page 1.jpg)
![single-page-1](figures/single-page-1.jpg)
- Column Mode
- Column mode
**Figure 2** Column layout
**Figure 2** Column mode
![en-us_image_0000001562820845](figures/en-us_image_0000001562820845.png)
Set mode to NavigationMode.Split. The Navigation component is displayed in columns.
Set **mode** to **NavigationMode.Split** so that the **\<Navigation>** component is displayed in columns.
```ts
......@@ -111,18 +111,19 @@ The Navigation component uses the mode attribute to set the page display mode.
}
```
![Column](figures/Column.jpg)
![column](figures/column.jpg)
## Setting the Title Bar Mode
The title bar is on the top of the page and is used to display the page name and operation entry. The Navigation component uses the titleMode property to set the title bar mode.
The title bar is on the top of the page and is used to display the page name and operation entry. The **\<Navigation>** component uses the **titleMode** attribute to set the title bar mode.
- Mini mode
Common title bar, which is used when the title of a level-1 page does not need to be highlighted.
**Figure 3** Title bar in Mini mode
Applicable when the title of a level-1 page does not need to be highlighted.
**Figure 3** Title bar in Mini mode
![mini](figures/mini.jpg)
......@@ -135,10 +136,11 @@ The title bar is on the top of the page and is used to display the page name and
- Full mode
Emphasis title bar, which is used when the title of a level-1 page needs to be highlighted.
**Figure 4** Title bar in Full mode
Applicable when the title of a level-1 page needs to be highlighted.
**Figure 4** Title bar in Full mode
![free1](figures/free1.jpg)
......@@ -150,9 +152,9 @@ The title bar is on the top of the page and is used to display the page name and
```
## Setting Menu Bar
## Setting the Menu Bar
The menu bar is in the upper right corner of the Navigation component. Developers can set the menu bar through the menus property. The menus supports two parameter types: Array&lt;[NavigationMenuItem](../reference/arkui-ts/ts-basic-components-navigation.md#navigationmenuitem %E7%B1%BB %E5%9E %8B %E8%AF %B4%E6%98%8E)&gt and CustomBuilder. When the Array<NavigationMenuItem> type is used, a maximum of three icons can be displayed in portrait mode and a maximum of five icons can be displayed in landscape mode. Extra icons will be placed in the automatically generated More icons.
The menu bar is in the upper right corner of the **\<Navigation>** component. You can set the menu bar through the **menus** attribute, which supports two parameter types: Array&lt;[NavigationMenuItem](../reference/arkui-ts/ts-basic-components-navigation.md#navigationmenuitem)&gt and CustomBuilder. When the Array\<NavigationMenuItem> type is used, a maximum of three icons can be displayed in portrait mode and a maximum of five icons can be displayed in landscape mode. Extra icons will be placed in the automatically generated More icons.
**Figure 5** Menu bar with three icons
......@@ -184,7 +186,7 @@ Navigation() {
## Setting the Toolbar
The toolbar is located at the bottom of the Navigation component. Developers can set the toolbar by setting the toolbar properties.
The toolbar is located at the bottom of the **\<Navigation>** component. You can set the toolbar through the **toolBar** attribute.
**Figure 7** Toolbar
......
# Page Transition Animation
During page redirection, one page disappears and the other page appears. In this case, you can configure the page transition parameters of each page to customize the page transition effect. [Page transition](../reference/arkui-ts/ts-page-transition-animation.md) effect is written in the **pageTransition** API. PageTransitionEnter and PageTransitionExit are used to specify the animation effect of page entry and exit.
During page redirection, one page disappears and the other page appears. You can customize the [page transition effects](../reference/arkui-ts/ts-page-transition-animation.md) for these pages through the **pageTransition** API. Specifically, **PageTransitionEnter** defines the page entrance animation, while **PageTransitionExit** defines the page exit animation.
PageTransitionEnter's interface is:
API of **PageTransitionEnter**:
......@@ -13,7 +13,7 @@ PageTransitionEnter({type?: RouteType,duration?: number,curve?: Curve | string,d
```
The interface of PageTransitionExit is:
API of **PageTransitionExit**:
......@@ -22,24 +22,24 @@ PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,de
```
Defines the PageTransitionEnter and PageTransitionExit components. The slide, translate, scale, and opacity attributes can be used to define different page transition effects. For PageTransitionEnter, these effects indicate the start value during entry. For PageTransitionExit, these effects indicate the end value during exit. This method is similar to that for configuring component transition. In addition, PageTransitionEnter provides the onEnter interface to call back the entry animation of a customized page, and PageTransitionExit provides the onExit interface to call back the exit animation of a customized page.
Both **PageTransitionEnter** and **PageTransitionExit** contain the **slide**, **translate**, **scale**, and **opacity** attributes. For **PageTransitionEnter**, these attributes indicate the start values for page entrance. For **PageTransitionExit**, these attributes indicate the end values for page exit. In this sense, configuration of page transition is similar to that of component transition. **PageTransitionEnter** provides the **onEnter** callback, and **PageTransitionExit** provides the **onExit** callback.
The type parameter in the preceding interface indicates the type of the route that takes effect, which may be confused by developers. One of the two pages must exit and the other must enter. If you switch from page A to page B through the router.pushUrl operation, page A exits and the exit animation is displayed. Page B enters and the entry animation is displayed. If the router.back operation is performed to return from page B to page A, page B exits and the exit animation is displayed. Page A enters and the entry animation is displayed. That is, PageTransitionEnter of a page may be an entry animation of a new page caused by a new page (push, stack), or an entry animation of an old page in a page stack caused by a page return (back, pop, stack). To distinguish the two types of entry animations, the type parameter is provided so that developers can define all types of page transition effects.
In the preceding APIs, the **type** parameter indicates the route type used in page navigation. Each page transition involves exit of one page and entrance of the other. If you switch from page A to page B through the **router.pushUrl** operation, page A exits, with the exit animation applied; and page B enters, with the entrance animation applied. If you switch from page B back to page A through the **router.back** operation, page B exits, , with the exit animation applied; and page A enters, with the entrance animation applied. That is, **PageTransitionEnter** of a page may be an entrance animation of a new page (pushed to the stack) or of an existing page (popped from the stack). To distinguish these two types of entrance animations, the **type** parameter is provided.
## Set type to RouteType.None.
## Setting type to RouteType.None
If the value of type is RouteType.None, the push and pop operations on the page stack are valid. The default value of type is RouteType.None.
When **type** is set to **RouteType.None** (default value), the page transition animations work for both the push and pop operations in the page stack.
```ts
// page A
pageTransition() {
// Define the effect when the page is displayed. The page slides in from the left for 1200 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1200 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.None, duration: 1200 })
.slide(SlideEffect.Left)
// Define the effect when the page exits. The page slides out to the left for 1000 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the left, with the duration of 1000 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.None, duration: 1000 })
.slide(SlideEffect.Left)
}
......@@ -50,48 +50,48 @@ pageTransition() {
```ts
// page B
pageTransition() {
// Define the effect when the page is displayed. The page slides in from the right for 1000 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the right, with the duration of 1000 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.None, duration: 1000 })
.slide(SlideEffect.Right)
// Define the effect when the page exits. The page slides out to the right for 1200 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the right, with the duration of 1200 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.None, duration: 1200 })
.slide(SlideEffect.Right)
}
```
Assume that the page stack is in the standard instance mode, that is, duplicate pages are allowed in the page stack. There may be four scenarios. The following table lists the page transition effects.
Assume that the page stack is in the multi-instance mode, that is, duplicate pages are allowed in the page stack. There may be four scenarios. The following table lists the page transition effects.
| Route operations | Transition effect of page A | Transition effect of page B |
| Route Operation | Page A Transition Effect | Page B Transition Effect |
| ---------------------------- | ---------------------------------- | ---------------------------------- |
| router.pushUrl. The new page B is displayed from page A.| Exit the page. The PageTransitionExit takes effect and slides to the left to display the screen. | The page is displayed. PageTransitionEnter takes effect and slides from the right to the screen.|
| router.back: Return from page B to page A. | The page is displayed, PageTransitionEnter takes effect, and you can slide from the left to the screen.| Exit the page. The PageTransitionExit takes effect and slides out of the screen to the right. |
| router.pushUrl. The new page A is displayed from page B.| The page is displayed, PageTransitionEnter takes effect, and you can slide from the left to the screen.| Exit the page. The PageTransitionExit takes effect and slides out of the screen to the right. |
| router.back: Return from page A to page B. | Exit the page. The PageTransitionExit takes effect and slides to the left to display the screen. | The page is displayed. PageTransitionEnter takes effect and slides from the right to the screen.|
| **router.pushUrl** – redirection from page A to new page B.| The page exits. The animation defined by **PageTransitionExit** is applied. In the example, the page slides out from the left of the screen. | The page enters. The animation defined by **PageTransitionEnter** is applied. In the example, the page slides in from the right of the screen.|
| **router.back** – redirection from page B back to page A. | The page enters. The animation defined by **PageTransitionEnter** is applied. In the example, the page slides in from the left of the screen.| The page exits. The animation defined by **PageTransitionExit** is applied. In the example, the page slides out from the right of the screen. |
| **router.pushUrl** – redirection from page B to new page A.| The page enters. The animation defined by **PageTransitionEnter** is applied. In the example, the page slides in from the left of the screen.| The page exits. The animation defined by **PageTransitionExit** is applied. In the example, the page slides out from the right of the screen. |
| **router.back** – redirection from page A back to page B. | The page exits. The animation defined by **PageTransitionExit** is applied. In the example, the page slides out from the left of the screen. | The page enters. The animation defined by **PageTransitionEnter** is applied. In the example, the page slides in from the right of the screen.|
If you want the page accessed by pushUrl to always slide in from the right and the page exited by back to always slide out from the right, the third and fourth cases in the preceding table do not meet the requirements. In this case, you need to define the transition effects of the four pages.
If you want the page accessed by **router.pushUrl** to always slide in from the right and the page exited by **router.back** to always slide out from the right, the third and fourth cases in the preceding table do not meet the requirements. In this case, you need to define four page transition effects.
## Set type to RouteType.Push or RouteType.Pop.
## Setting type to RouteType.Push or RouteType.Pop
If type is set to RouteType.Push, this parameter is valid only for the push operation of the page stack. If type is set to RouteType.Pop, this parameter is valid only for the pop operation of the page stack.
When **type** is set to **RouteType.Push**, the page transition animations work for only both the push operations in the page stack. When **type** is set to **RouteType.Pop**, the page transition animations work for only both the pop operations in the page stack.
```ts
// page A
pageTransition() {
// Define the effect when the page is entered. The page slides in from the right for 1200 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the right, with the duration of 1200 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Push, duration: 1200 })
.slide(SlideEffect.Right)
// Define the effect when the page is entered. The page slides in from the left for 1200 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1200 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Pop, duration: 1200 })
.slide(SlideEffect.Left)
// Define the effect when the page exits. The page slides out to the left for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page exit animation to sliding out from the left, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
// Define the effect when the page exits. The page slides out to the right for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the right, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
......@@ -102,41 +102,41 @@ pageTransition() {
```ts
// page B
pageTransition() {
// Define the effect when the page is entered. The page slides in from the right for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the right, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
//Define the effect when the page is entered. The page slides in from the left for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
// Define the effect when the page exits. The page slides out to the left for 1200 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page exit animation to sliding out from the left, with the duration of 1200 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Push, duration: 1200 })
.slide(SlideEffect.Left)
// Define the effect when the page exits. The page slides out to the right for 1200 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the right, with the duration of 1200 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Pop, duration: 1200 })
.slide(SlideEffect.Right)
}
```
The preceding code completely defines all possible page transition styles. Assume that the page stack is in the standard instance mode, that is, duplicate pages are allowed in the page stack. There may be four scenarios. The following table lists the page transition effects.
The preceding code defines page transition effects for all possibles scenarios. Assume that the page stack is in the multi-instance mode, that is, duplicate pages are allowed in the page stack. There may be four scenarios. The following table lists the page transition effects.
| Route operations | Transition effect of page A | Transition effect of page B |
| Route Operation | Page A Transition Effect | Page B Transition Effect |
| ---------------------------- | ---------------------------------------- | ---------------------------------------- |
| router.pushUrl. The new page B is displayed from page A.| The page exits. The transition style of PageTransitionExit whose type is RouteType.Push takes effect. The screen slides out to the left.| The page is displayed. The transition style of PageTransitionEnter whose type is RouteType.Push takes effect. The page slides from the right to the screen.|
| router.back: Return from page B to page A. | The page is displayed. The transition style of PageTransitionEnter whose type is RouteType.Pop takes effect. Slide from the left to the screen.| The page exits. The transition style of PageTransitionExit whose type is RouteType.Pop takes effect. The screen slides out to the right.|
| router.pushUrl. The new page A is displayed from page B.| The page is displayed. The transition style of PageTransitionEnter whose type is RouteType.Push takes effect. The page slides from the right to the screen.| The page exits. The transition style of PageTransitionExit whose type is RouteType.Push takes effect. The screen slides out to the left.|
| router.back: Return from page A to page B. | The page exits. The transition style of PageTransitionExit whose type is RouteType.Pop takes effect. The screen slides out to the right.| The page is displayed. The transition style of PageTransitionEnter whose type is RouteType.Pop takes effect. Slide from the left to the screen.|
| **router.pushUrl** – redirection from page A to new page B.| The page exits. The transition style of **PageTransitionExit** whose **type** is **RouteType.Push** takes effect. The page slides out from the left of the screen.| The page enters. The transition style of **PageTransitionEnter** whose **type** is **RouteType.Push** takes effect. The page slides in from the right of the screen.|
| **router.back** – redirection from page B back to page A. | The page enters. The transition style of **PageTransitionEnter** whose **type** is **RouteType.Pop** takes effect. The page slides in from the left of the screen.| The page exits. The transition style of **PageTransitionExit** whose **type** is **RouteType.Pop** takes effect. The page slides out from the right of the screen.|
| **router.pushUrl** – redirection from page B to new page A.| The page enters. The transition style of **PageTransitionEnter** whose **type** is **RouteType.Push** takes effect. The page slides in from the right of the screen.| The page exits. The transition style of **PageTransitionExit** whose **type** is **RouteType.Push** takes effect. The page slides out from the left of the screen.|
| **router.back** – redirection from page A back to page B. | The page exits. The transition style of **PageTransitionExit** whose **type** is **RouteType.Pop** takes effect. The page slides out from the right of the screen.| The page enters. The transition style of **PageTransitionEnter** whose **type** is **RouteType.Pop** takes effect. The page slides in from the left of the screen.|
>**NOTE**
>
> 1. The transition style of each page can be independently configured by developers. However, the transition involves two pages. Developers need to consider the transition effect of the two pages, for example, the transition duration.
> 1. The transition style of each page can be independently configured. However, as each transition involves two pages, take into account the smoothness between page transitions, for example, the transition duration.
>
> 2. If no matching page transition style is defined, the page uses the default page transition style.
> 2. If no page transition style is defined, a page uses the default page transition style.
## Disable the transition of a page.
## Disabling Page Transition
```ts
......@@ -147,17 +147,17 @@ pageTransition() {
```
You can set the page transition duration to 0 so that no page transition animation is displayed on the page.
You can disable the transition animation of a page by setting the page transition duration to 0.
## Example Scenario
## Example
The following describes an example of a page transition animation that defines all four page transition styles.
In the following example, page transition animations are defined for all four page transition scenarios.
```ts
// page A
// PageTransitionSrc1
import router from '@ohos.router';
@Entry
@Component
......@@ -168,18 +168,18 @@ struct PageTransitionSrc1 {
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) //Load the image synchronously so that the image has been loaded when the page is displayed.
.syncLoad(true) // Load the image synchronously so that the image has been loaded when the page is displayed.
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
//Route to the next page and perform the push operation.
// Navigate to the next page, which is a push operation.
router.pushUrl({ url: 'pages/myTest/pageTransitionDst1' });
})
Button("back")
.onClick(() => {
//Return to the previous page, which is equivalent to the pop operation.
// Return to the previous page, which is equivalent to the pop operation.
router.back();
})
}.justifyContent(FlexAlign.Center)
......@@ -189,16 +189,16 @@ struct PageTransitionSrc1 {
}
pageTransition() {
//Define the effect when the page is entered. The page slides in from the right for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the right, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
//Define the effect when the page is entered. The page slides in from the left for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. The page slides out to the left for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page exit animation to sliding out from the left, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. The page slides out to the right for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the right, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
......@@ -209,7 +209,7 @@ struct PageTransitionSrc1 {
```ts
// page B
// PageTransitionDst1
import router from '@ohos.router';
@Entry
@Component
......@@ -220,18 +220,18 @@ struct PageTransitionDst1 {
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) //Load the image synchronously so that the image has been loaded when the page is displayed.
.syncLoad(true) // Load the image synchronously so that the image has been loaded when the page is displayed.
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
//Route to the next page and perform the push operation.
// Navigate to the next page, which is a push operation.
router.pushUrl({ url: 'pages/myTest/pageTransitionSrc1' });
})
Button("back")
.onClick(() => {
//Return to the previous page, which is equivalent to the pop operation.
// Return to the previous page, which is equivalent to the pop operation.
router.back();
})
}.justifyContent(FlexAlign.Center)
......@@ -241,16 +241,16 @@ struct PageTransitionDst1 {
}
pageTransition() {
//Define the effect when the page is entered. The page slides in from the right for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the right, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
//Define the effect when the page is entered. The page slides in from the left for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. The page slides out to the left for 1000 ms. The effect takes effect only when the push operation is performed on the page stack.
// Configure the page exit animation to sliding out from the left, with the duration of 1000 ms. The settings take effect only when the push operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. The page slides out to the right for 1000 ms. The effect takes effect only when the pop operation is performed on the page stack.
// Configure the page exit animation to sliding out from the right, with the duration of 1000 ms. The settings take effect only when the pop operation is performed on the page stack.
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
......@@ -262,12 +262,12 @@ struct PageTransitionDst1 {
![pageTransition_PushPop](figures/pageTransition_PushPop.gif)
The following describes an example of the page transition animation whose type is None.
In the following example, **type** is set to **RouteType.None**.
```ts
// page A
// PageTransitionSrc2
import router from '@ohos.router';
@Entry
@Component
......@@ -278,18 +278,18 @@ struct PageTransitionSrc2 {
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) //Load the image synchronously so that the image has been loaded when the page is displayed.
.syncLoad(true) // Load the image synchronously so that the image has been loaded when the page is displayed.
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
//Route to the next page and perform the push operation.
// Navigate to the next page, which is a push operation.
router.pushUrl({ url: 'pages/myTest/pageTransitionDst2' });
})
Button("back")
.onClick(() => {
//Return to the previous page, which is equivalent to the pop operation.
// Return to the previous page, which is equivalent to the pop operation.
router.back();
})
}.justifyContent(FlexAlign.Center)
......@@ -299,10 +299,10 @@ struct PageTransitionSrc2 {
}
pageTransition() {
//Define the effect when the page is displayed. The page slides in from the left for 1000 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1000 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionEnter({ duration: 1000 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. Compared with the normal page position, the page position is shifted by 100 vp in the x direction and 100 vp in the y direction. The transparency changes to 0. The duration is 1200 ms. The effect takes effect regardless of whether the push or pop operation is performed on the page stack.
// Configure the page exit animation to translating by 100 vp along the x- and y-axes and changing the opacity to 0, with the duration of 1200 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionExit({ duration: 1200 })
.translate({ x: 100.0, y: 100.0 })
.opacity(0)
......@@ -313,7 +313,7 @@ struct PageTransitionSrc2 {
```ts
// page B
// PageTransitionDst2
import router from '@ohos.router';
@Entry
@Component
......@@ -324,18 +324,18 @@ struct PageTransitionDst2 {
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) //Load the image synchronously so that the image has been loaded when the page is displayed.
.syncLoad(true) // Load the image synchronously so that the image has been loaded when the page is displayed.
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
//Route to the next page and perform the push operation.
// Navigate to the next page, which is a push operation.
router.pushUrl({ url: 'pages/myTest/pageTransitionSrc2' });
})
Button("back")
.onClick(() => {
//Return to the previous page, which is equivalent to the pop operation.
// Return to the previous page, which is equivalent to the pop operation.
router.back();
})
}.justifyContent(FlexAlign.Center)
......@@ -345,10 +345,10 @@ struct PageTransitionDst2 {
}
pageTransition() {
//Define the effect when the page is displayed. The page slides in from the left for 1200 ms. The effect takes effect no matter whether the push or pop operation is performed on the page stack.
// Configure the page entrance animation to sliding in from the left, with the duration of 1200 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionEnter({ duration: 1200 })
.slide(SlideEffect.Left)
//Define the effect when the page exits. Compared with the normal page position, the page position is shifted by 100 vp in the x direction and 100 vp in the y direction. The transparency changes to 0. The duration is 1000 ms. The effect takes effect regardless of whether the push or pop operation is performed on the page stack.
// Configure the page exit animation to translating by 100 vp along the x- and y-axes and changing the opacity to 0, with the duration of 1000 ms. The settings take effect no matter whether the push or pop operation is performed on the page stack.
PageTransitionExit({ duration: 1000 })
.translate({ x: 100.0, y: 100.0 })
.opacity(0)
......
......@@ -2,7 +2,7 @@
Poor-performing code may work, but will take away from your application performance. This topic presents a line-up of recommendations that you can take to improve your implementation, thereby avoiding possible performance drop.
## Lazy Loading
## Using Lazy Loading
When developing a long list, use of loop rendering, as in the code snippet below, can greatly slow down page loading and increase server load.
......@@ -131,6 +131,226 @@ struct MyComponent {
The preceding code initializes only three list elements during page loading and loads a new list item each time a list element is clicked.
## Setting Width and Height for \<List> Components
When a **\<List>** component is nested within a **\<Scroll>** component, all of its content will be loaded if its width and height is not specified, which may result in performance drop.
> **NOTE**
>
> When a **\<List>** component is nested within a **\<Scroll>** component:
>
> - If the width and height of the **\<List>** component are not set, all its child components are laid out.
>
> - If the width and height of the **\<List>** component are set, only child components within its display area are laid out.
>
> - When [ForEach](../quick-start/arkts-rendering-control-foreach.md) is used to load child components in the **\<List>** component, all child components are laid out, regardless of whether the width and height are set.
>
> - When [LazyForEach](../quick-start/arkts-rendering-control-lazyforeach.md) is used to load child components in the **\<List>** component, all child components are laid out if the component does not have its width and height specified; and only child components within its display area are laid out if the component has its width and height specified.
```ts
class BasicDataSource implements IDataSource {
private listeners: DataChangeListener[] = []
public totalCount(): number {
return 0
}
public getData(index: number): any {
return undefined
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener')
this.listeners.push(listener)
}
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener')
this.listeners.splice(pos, 1)
}
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded()
})
}
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index)
})
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index)
})
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index)
})
}
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to)
})
}
}
class MyDataSource extends BasicDataSource {
private dataArray: Array<string> = new Array(100).fill('test')
public totalCount(): number {
return this.dataArray.length
}
public getData(index: number): any {
return this.dataArray[index]
}
public addData(index: number, data: string): void {
this.dataArray.splice(index, 0, data)
this.notifyDataAdd(index)
}
public pushData(data: string): void {
this.dataArray.push(data)
this.notifyDataAdd(this.dataArray.length - 1)
}
}
@Entry
@Component
struct MyComponent {
private data: MyDataSource = new MyDataSource()
build() {
Scroll() {
List() {
LazyForEach(this.data, (item: string, index: number) => {
ListItem() {
Row() {
Text('item value: ' + item + (index + 1)).fontSize(20).margin(10)
}
}
})
}
}
}
}
```
In the above scenario, you are advised to set the width and height for the **\<List>** component.
```ts
class BasicDataSource implements IDataSource {
private listeners: DataChangeListener[] = []
public totalCount(): number {
return 0
}
public getData(index: number): any {
return undefined
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener')
this.listeners.push(listener)
}
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener')
this.listeners.splice(pos, 1)
}
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded()
})
}
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index)
})
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index)
})
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index)
})
}
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to)
})
}
}
class MyDataSource extends BasicDataSource {
private dataArray: Array<string> = new Array(100).fill('test')
public totalCount(): number {
return this.dataArray.length
}
public getData(index: number): any {
return this.dataArray[index]
}
public addData(index: number, data: string): void {
this.dataArray.splice(index, 0, data)
this.notifyDataAdd(index)
}
public pushData(data: string): void {
this.dataArray.push(data)
this.notifyDataAdd(this.dataArray.length - 1)
}
}
@Entry
@Component
struct MyComponent {
private data: MyDataSource = new MyDataSource()
build() {
Scroll() {
List() {
LazyForEach(this.data, (item: string, index: number) => {
ListItem() {
Text('item value: ' + item + (index + 1)).fontSize(20).margin(10)
}.width('100%')
})
}.width('100%').height(500)
}.backgroundColor(Color.Pink)
}
}
```
![list1](figures/list1.gif)
## Prioritizing Conditional Rendering over Visibility Control
Use of the visibility attribute to hide or show a component, as in the code snippet below, results in re-creation of the component, leading to performance drop.
......
# Menu
Menu is a menu interface, which is generally used for right-click pop-up windows and click pop-up windows. For details, see [Menu Control] (../reference/arkui-ts/ts-universal-attributes-menu.md).
You can use menu APIs to display a context menu – a vertical list of items displayed by long pressing, clicking, or right-clicking a component. For details, see [Menu Control](../reference/arkui-ts/ts-universal-attributes-menu.md).
## Creating a Menu in the Default Style
The bindMenu interface needs to be called to implement menus. The bindMenu responds to the tap event of the bound widget. After the widget is bound, the widget is displayed after you tap the corresponding widget using gestures.
Use the **bindMenu** API to implement a menu. **bindMenu** responds to the click event of the bound component. When the bound component is clicked, the menu is displayed.
......@@ -26,12 +26,12 @@ Button('click for Menu')
![en-us_image_0000001562940565](figures/en-us_image_0000001562940565.png)
## Creating a Menu with a Customized Style
## Creating a Menu in a Custom Style
If the default style does not meet development requirements, you can use \@CustomBuilder to customize menu content. Menus can be customized through the bindContextMenu interface.
If the default style does not meet requirements, you can use \@CustomBuilder to customize menu content. Menus can also be customized through the **bindMenu** API.
### \@Builder Develop the content in the menu.
### \@Builder: Customizing Menu Content
```ts
......@@ -49,17 +49,17 @@ SubMenu() {
@Builder
MyMenu(){
Menu() {
MenuItem({ startIcon: $r("app.media.icon"), content: " menu option "})
MenuItem({ startIcon: $r("app.media.icon"), content: " menu option "}).enabled(false)
MenuItem({ startIcon: $r("app.media.icon"), content: "Menu option" })
MenuItem({ startIcon: $r("app.media.icon"), content: "Menu option" }).enabled(false)
MenuItem({
startIcon: this.iconStr,
content: "Menu option",
endIcon: $r("app.media.arrow_right_filled"),
//When the builder parameter is set, it indicates that a submenu is bound to menuItem. When you hover the cursor over the menu item, the submenu is displayed.
// When the builder parameter is set, it indicates that a submenu is bound to a menu item. When the user hovers the cursor over the menu item, the submenu is displayed.
builder: this.SubMenu.bind(this),
})
MenuItemGroup ({ header: 'Subtitle' }) {
MenuItem ({ content: "MenuOptions" })
MenuItem ({ content: "Menu option" })
.selectIcon(true)
.selected(this.select)
.onChange((selected) => {
......@@ -70,7 +70,7 @@ MyMenu(){
startIcon: $r("app.media.view_list_filled"),
content: "Menu option",
endIcon: $r("app.media.arrow_right_filled"),
builder: this.SubMenu.bind(this)\
builder: this.SubMenu.bind(this)
})
}
MenuItem({
......@@ -84,7 +84,7 @@ MyMenu(){
```
### Binding the bindMenu Attribute to a Component
### Using the bindMenu Attribute to Bind a Component
```ts
......@@ -96,14 +96,14 @@ Button('click for Menu')
![en-us_image_0000001511580924](figures/en-us_image_0000001511580924.png)
## Create a menu that supports right-click or touch and hold.
## Creating a Context Menu Displayed Upon Right-clicking or Long Pressing
The bindContextMenu interface is used to customize menus and trigger menu pop-up by right-clicking or pressing and holding. The menu items that are displayed using bindContextMenu are in an independent child window and can be displayed outside the application window.
Use the **bindContextMenu** API to customize the menu content and menu popup mode: right-click or long press. The menu items that are displayed using **bindContextMenu** are in an independent child window and can be displayed outside the application window.
- [@Builder development menu content] (#builder development menu content) is the same as the preceding content.
- The content in the @Builder is the same as that in the preceding section.
- Confirm the menu pop-up mode and use the bindContextMenu property to bind the component. In the example, the shortcut menu is displayed.
- Check the menu popup mode and bind the component through the **bindContextMenu** attribute. In the example, the menu is displayed upon right-clicking.
```ts
Button('click for Menu')
......
# Page Routing
Page routing refers to the jump and data transfer between different pages in an application. The OpenHarmony provides the Router module. Through different URLs, you can easily route pages and access different pages. This document describes the functions provided by the Router module from the following aspects: [Page Jump] (#Page Jump), [Page Return] (#Page Return), and [Adding a Query Box Before Page Return] (#Adding a Query Box Before Page Return).
Page routing refers to the redirection and data transfer between different pages in an application. In OpenHarmony, page routing can be implemented through APIs of the **Router** module. Through different URLs, you can easily navigate users through pages. This document describes the functions provided by the **Router** module from the following aspects: [Page Redirection](#page-redirection), [Page Return](#page-return), and [Adding a Confirmation Dialog Box Before Page Return](#adding-a-confirmation-dialog-box-before-page-return).
## Page redirection
## Page Redirection
Page jumping is an important part of the development process. When using an application, you usually need to jump between different pages, and sometimes you need to pass data from one page to another.
Page redirection is an important part of the development process. When using an application, you usually need to jump between different pages, and sometimes you need to pass data from one page to another.
**Figure 1** Page redirection
![router-jump-to-detail](figures/router-jump-to-detail.gif)
The Router module provides two jump modes: [router.pushUrl()](../reference/apis/js-apis-router.md#routerpushurl9) and [router.replaceUrl()](../reference/apis/js-apis-router.md#routerreplaceurl9). The two modes determine whether the target page will replace the current page.
The **Router** module provides two redirection modes: [router.pushUrl()](../reference/apis/js-apis-router.md#routerpushurl9) and [router.replaceUrl()](../reference/apis/js-apis-router.md#routerreplaceurl9). The two modes determine whether the target page will replace the current page.
- router.pushUrl(): The target page does not replace the current page. Instead, it is pushed into the page stack (../application-models/page-mission-stack.md). In this way, the state of the current page can be retained, and you can return to the current page by pressing the Back key or calling the [router.back()](../reference/apis/js-apis-router.md#routerback) method.
- **router.pushUrl()**: The target page does not replace the current page. Instead, it is pushed into the [page stack](../application-models/page-mission-stack.md). In this way, the state of the current page can be retained, and users can return to the current page by pressing the back button or calling the [router.back()](../reference/apis/js-apis-router.md#routerback) API.
- router.replaceUrl(): The target page replaces the current page and destroys the current page. In this way, the resources of the current page can be released and the current page cannot be returned.
- **router.replaceUrl()**: The target page replaces the current page and destroys the current page. In this way, the resources of the current page can be released, and users cannot return to the current page.
>**Notes:**
>**NOTE**
>
>The maximum capacity of a page stack is 32 pages. If this limit is exceeded, the [router.clear()](../reference/apis/js-apis-router.md#routerclear) method can be called to clear the historical page stack and release the memory space.
>The maximum capacity of a page stack is 32 pages. If this limit is exceeded, the [router.clear()](../reference/apis/js-apis-router.md#routerclear) API can be called to clear the historical page stack and free the memory.
In addition, the Router module provides two instance modes: Standard and Single. The two modes determine whether the target URL corresponds to multiple instances.
The **Router** module also provides two instance modes: **Standard** and **Single**. The two modes determine whether the target URL corresponds to multiple instances.
- Standard: standard instance mode, which is the default instance mode. Each time this method is called, a target page is created and pushed to the top of the stack.
- **Standard**: standard instance mode, which is the default instance mode. Each time this API is called, a target page is created and pushed to the top of the stack.
- Single: single-instance mode. If the URL of the target page already exists in the page stack, the page with the same URL closest to the top of the stack is moved to the top of the stack and reloaded. If the URL of the target page does not exist in the page stack, the page is redirected in standard mode.
- **Single**: singleton mode. If the URL of the target page already exists in the page stack, the page with the same URL closest to the top of the stack is moved to the top of the stack and reloaded. If the URL of the target page does not exist in the page stack, the page is redirected in standard mode.
Before using the Router function, you need to import the Router module to the code.
Before using the **Router** module, you need to import it to the code.
```ts
import router from '@ohos.router';
```
- Scenario 1: There is a home page (Home) and a details page (Detail). You want to click an offering on the home page to go to the details page. In addition, the home page needs to be retained in the page stack so that the status can be restored when the page is returned. In this scenario, you can use the pushUrl() method and use the Standard instance mode (or omit it).
- Scenario 1: There is a home page (**Home**) and a details page (**Detail**). You want to click an offering on the home page to go to the details page. In addition, the home page needs to be retained in the page stack so that the status can be restored when the page is returned. In this scenario, you can use the **pushUrl()** API and use the **Standard** instance mode (which can also be omitted).
```ts
//On the Home page
// On the Home page
function onJumpClick(): void {
router.pushUrl({
url: 'pages/Detail' //Target URL.
url: 'pages/Detail' // Target URL.
}, router.RouterMode.Standard, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
......@@ -54,16 +54,16 @@ import router from '@ohos.router';
>**NOTE**
>
>In standard instance mode, the router.RouterMode.Standard parameter can be omitted.
>In **Standard** instance mode, the **router.RouterMode.Standard** parameter can be omitted.
- Scenario 2: There is a login page (Login) and a personal center page (Profile). After a user successfully logs in from the login page, the personal center page is displayed. At the same time, the login page is destroyed and the application is directly exited when the page is returned. In this scenario, you can use the replaceUrl() method and use the Standard instance mode (or omit it).
- Scenario 2: There is a login page (**Login**) and a personal center page (**Profile**). After a user successfully logs in from the **Login** page, the **Profile** page is displayed. At the same time, the **Login** page is destroyed, and the application exits when the back button is pressed. In this scenario, you can use the **replaceUrl()** API and use the Standard instance mode (which can also be omitted).
```ts
//On the Login page
// On the Login page
function onJumpClick(): void {
router.replaceUrl({
url: 'pages/Profile' //Target URL.
url: 'pages/Profile' // Target URL.
}, router.RouterMode.Standard, (err) => {
if (err) {
console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
......@@ -76,16 +76,16 @@ import router from '@ohos.router';
>**NOTE**
>
>In standard instance mode, the router.RouterMode.Standard parameter can be omitted.
>In **Standard** instance mode, the **router.RouterMode.Standard** parameter can be omitted.
- Scenario 3: There is a setting page (Setting) and a theme switch page (Theme). You want to click the theme option on the setting page to go to the theme switch page. In addition, ensure that only one theme switching page exists in the page stack at a time. When the page is returned, the setting page is displayed. In this scenario, the pushUrl() method can be used and the Single instance mode can be used.
- Scenario 3: There is a setting page (**Setting**) and a theme switching page (**Theme**). You want to click a theme option on the **Setting** page to go to the **Theme** page. In addition, you want to ensure that only one **Theme** page exists in the page stack at a time. When the back button is clicked on the **Theme** page, the **Setting** page is displayed. In this scenario, you can use the **pushUrl()** API and use the **Single** instance mode.
```ts
//On the Setting page
// On the Setting page
function onJumpClick(): void {
router.pushUrl({
url: 'pages/Theme' //Target URL.
url: 'pages/Theme' // Target URL.
}, router.RouterMode.Single, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
......@@ -96,14 +96,14 @@ import router from '@ohos.router';
}
```
- Scenario 4: There is a search result list page (SearchResult) and a search result details page (SearchDetail). You want to click a result on the search result list page to go to the search result details page. In addition, if the result has been viewed, you do not need to create a details page. Instead, you can directly go to the existing details page. In this scenario, the replaceUrl() method can be used and the Single instance mode can be used.
- Scenario 4: There is a search result list page (**SearchResult**) and a search result details page (**SearchDetail**). You want to click a result on the **SearchResult** page to go to the **SearchDetail** page. In addition, if the result has been viewed before, clicking the result displays the existing details page, instead of creating a new one. In this scenario, you can use the **replaceUrl()** API and use the **Single** instance mode.
```ts
//On the SearchResult page
// On the SearchResult page
function onJumpClick(): void {
router.replaceUrl({
url: 'pages/SearchDetail' //Target URL.
url: 'pages/SearchDetail' // Target URL.
}, router.RouterMode.Single, (err) => {
if (err) {
console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
......@@ -113,9 +113,9 @@ import router from '@ohos.router';
}
```
The preceding scenario does not involve parameter transfer.
The preceding scenarios do not involve parameter transfer.
If you need to transfer some data to the target page during redirection, you can add a params attribute and specify an object as a parameter when invoking the method of the Router module. Example:
If you need to transfer some data to the target page during redirection, you can add a **params** attribute and specify an object as a parameter when invoking an API of the **Router** module. Example:
```ts
......@@ -129,7 +129,7 @@ class DataModel {
}
function onJumpClick(): void {
//On the Home page
// On the Home page
let paramsInfo: DataModel = {
id: 123,
info: {
......@@ -138,8 +138,8 @@ function onJumpClick(): void {
};
router.pushUrl({
url: 'pages/Detail', //Target URL
params: paramsInfo // Add the params attribute to transfer customized parameters.
url: 'pages/Detail', // Target URL.
params: paramsInfo // Add the params attribute to transfer custom parameters.
}, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
......@@ -150,7 +150,7 @@ function onJumpClick(): void {
}
```
On the target page, you can call the [getParams()](../reference/apis/js-apis-router.md#routergetparams) method of the Router module to obtain the transferred parameters. Example:
On the target page, you can call the [getParams()](../reference/apis/js-apis-router.md#routergetparams) API of the **Router** module to obtain the transferred parameters. Example:
```ts
......@@ -164,18 +164,18 @@ const age = params['info'].age; // Obtain the value of the age attribute.
After a user completes an operation on a page, the user usually needs to return to the previous page or a specified page. In this case, the page return function is required. During the return process, the data may need to be transferred to the target page, which requires the data transfer function.
Figure 2 Page return
**Figure 2** Page return
![router-back-to-home](figures/router-back-to-home.gif)
Before using the Router function, you need to import the Router module to the code.
Before using the **Router** module, you need to import it to the code.
```ts
import router from '@ohos.router';
```
You can use any of the following methods to return to the page:
You can use any of the following methods to return to a page:
- Method 1: Return to the previous page.
......@@ -184,7 +184,7 @@ You can use any of the following methods to return to the page:
router.back();
```
In this mode, the previous page is returned, that is, the position of the previous page in the page stack. However, the previous page must exist in the page stack to return. Otherwise, the method is invalid.
This method allows you to return to the position of the previous page in the page stack. For this method to work, the previous page must exist in the page stack.
- Method 2: Return to the specified page.
......@@ -195,7 +195,7 @@ You can use any of the following methods to return to the page:
});
```
In this mode, you can return to a specified page. You need to specify the path of the target page. The target page can be returned only when it exists in the page stack.
This method allows you to return to a specified page. You need to specify the path of the target page. For this method to work, the target page must it exist in the page stack.
- Method 3: Return to the specified page and transfer custom parameter information.
......@@ -209,112 +209,112 @@ You can use any of the following methods to return to the page:
});
```
In this mode, you can not only return to the specified page, but also transfer custom parameter information when returning. The parameter information can be obtained and parsed by invoking the router.getParams() method on the target page.
This method not only allows you to return to the specified page, but also transfer custom parameter information when returning. The parameter information can be obtained and parsed by invoking the **router.getParams()** API on the target page.
On the target page, call the router.getParams() method at the position where parameters need to be obtained. For example, in the onPageShow() lifecycle callback:
On the target page, call the **router.getParams()** API at the position where parameters need to be obtained, for example, in the **onPageShow()** lifecycle callback:
```ts
onPageShow() {
const params = router.getParams(); //Obtain the transferred parameter object.
const info = params['info']; //Obtain the value of the info attribute.
const params = router.getParams(); // Obtain the transferred parameter object.
const info = params['info']; // Obtain the value of the info attribute.
}
```
>**NOTE**
>
>When the router.back() method is used to return to a specified page, the page is pushed to the top of the stack again, and all page stacks between the original top page (included) and the specified page (excluded) are destroyed.
>When the **router.back()** API is used to return to a specified page, the page is pushed to the top of the stack again, and all page stacks between the original top page (included) and the specified page (excluded) are destroyed.
>
> In addition, if the router.back() method is used to return to the original page, the original page will not be created repeatedly. Therefore, the variable declared using \@State will not be declared repeatedly, and the aboutToAppear() lifecycle callback of the page will not be triggered. If you want to use the customized parameters transferred from the return page on the original page, you can parse the parameters in the required position. For example, parameter parsing is performed in the onPageShow() lifecycle callback.
> If the **router.back()** method is used to return to the original page, the original page will not be created repeatedly. Therefore, the variable declared using \@State will not be declared repeatedly, and the **aboutToAppear()** lifecycle callback of the page will not be triggered. If you want to use the custom parameters transferred from the returned page on the original page, you can parse the parameters in the required position. For example, parameter parsing can be performed in the **onPageShow()** lifecycle callback.
## A query box is added before the page is returned.
## Adding a Confirmation Dialog Box Before Page Return
During application development, to prevent misoperations or data loss, a dialog box needs to be displayed before a user returns from one page to another, asking the user whether to perform the operation.
This document describes how to add a query box before returning to the page from two aspects: [System Default Query Box] (#System Default Query Box) and [Customized Query Box] (#Customized Query Box).
Such a dialog box can be in the [default style](#default-confirmation-dialog-box) or [custom style](#custom-confirmation-dialog-box).
Figure 3 Adding a query box before returning to the page
**Figure 3** Adding a confirmation dialog box before page return
![router-add-query-box-before-back](figures/router-add-query-box-before-back.gif)
### Default query box
### Default Confirmation Dialog Box
To implement this function, you can use the [router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9) and [router.back()](../reference/apis/js-apis-router.md#routerback) methods provided by the Router module.
To implement this function, you can use the [router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9) and [router.back()](../reference/apis/js-apis-router.md#routerback) APIs provided by the **Router** module.
Before using the Router function, you need to import the Router module to the code.
Before using the **Router** module, you need to import it to the code.
```ts
import router from '@ohos.router';
```
If you want to enable the function of returning to the query box on the target page, you need to call the [router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9) method to set the information about the returned query box before invoking the [router.back()](../reference/apis/js-apis-router.md#routerback) method. For example, define a click event processing function for the return button on the payment page:
To enable the confirmation dialog box for page return, call the [router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9) API (for setting the information about the dialog box), then the [router.back()](../reference/apis/js-apis-router.md#routerback) API. For example, define a click event processing function for the back button on the payment page:
```ts
//Define a click event processing function for the return button.
// Define a click event processing function for the back button.
function onBackClick(): void {
//Invoke the router.showAlertBeforeBackPage() method to set the information about the returned query box.
// Invoke the router.showAlertBeforeBackPage() API to set the information about the confirmation dialog box.
try {
router.showAlertBeforeBackPage({
message: 'You have not completed the payment. Are you sure you want to return?' //Set the content of the inquiry box.
message: 'Payment not completed yet. Are you sure you want to return?' // Set the content of the confirmation dialog box.
});
} catch (err) {
console.error(`Invoke showAlertBeforeBackPage failed, code is ${err.code}, message is ${err.message}`);
}
// Invoke the router.back() method to return to the previous page.
// Invoke the router.back() API to return to the previous page.
router.back();
}
```
The router.showAlertBeforeBackPage() method receives an object as a parameter. The object contains the following attributes:
The **router.showAlertBeforeBackPage()** API receives an object as a parameter. The object contains the following attributes:
- message: content of the query box. The value is of the string type.
If the interface is successfully called, the page is displayed on the target page and the query box is displayed. If the interface fails to be called, an exception is thrown and the error code and error information is obtained through err.code and err.message.
- **message**: content of the dialog box. The value is of the string type.
If the API is successfully called, the confirmation dialog box is displayed on the target page. Otherwise, an exception is thrown and the error code and error information is obtained through **err.code** and **err.message**.
When the user clicks Back, a confirmation dialog box is displayed, asking the user whether to confirm the return. If you select Cancel, the target page of the current page is displayed. If you select OK, the router.back() method is triggered and the jump is performed based on the parameters.
When the user clicks the back button, a confirmation dialog box is displayed, prompting the user to confirm their operation. If the user selects Cancel, the application stays on the current page. If the user selects OK, the **router.back()** API is triggered and the redirection is performed based on the parameters.
### Custom Inquiry Box
### Custom Confirmation Dialog Box
You can use the pop-up window (../reference/apis/js-apis-promptAction.md#promptactionshowdialog) or customize a pop-up window. In this way, the application interface can be different from the default query box of the system, thereby improving user experience of the application. This document uses a pop-up window as an example to describe how to customize a query box.
To implement a custom confirmation dialog box, use APIs in the [PromptAction](../reference/apis/js-apis-promptAction.md#promptactionshowdialog) module or customize a popup window. This topic uses the APIs in the **PromptAction** module an example to describe how to implement a custom confirmation dialog box.
Before using the Router function, you need to import the Router module to the code.
Before using the **Router** module, you need to import it to the code.
```ts
import router from '@ohos.router';
```
In the event callback, call the [promptAction.showDialog()](../reference/apis/js-apis-promptAction.md#promptactionshowdialog) method of the pop-up window.
In the event callback, call the [promptAction.showDialog()](../reference/apis/js-apis-promptAction.md#promptactionshowdialog) API of the **PromptAction** module.
```ts
function onBackClick() {
//The user-defined query dialog box is displayed.
// Display a custom confirmation dialog box.
promptAction.showDialog({
message:'You have not completed the payment. Are you sure you want to return?',
message:'Payment not completed yet. Are you sure you want to return?',
buttons: [
{
text: 'Cancel',
text: 'Cancel',
color: '#FF0000'
},
{
text: 'Confirm',
text: 'OK',
color: '#0099FF'
}
]
}).then((result) => {
if (result.index === 0) {
// The user clicks Cancel.
// The user selects Cancel.
console.info('User canceled the operation.');
} else if (result.index === 1) {
//The user clicks OK.
// The user selects OK.
console.info('User confirmed the operation.');
// Invoke the router.back() method to return to the previous page.
// Invoke the router.back() API to return to the previous page.
router.back();
}
}).catch((err) => {
......@@ -323,4 +323,4 @@ function onBackClick() {
}
```
When the user clicks Back, a user-defined query box is displayed, asking the user whether to confirm the return. If you select Cancel, the target page of the current page is displayed. If you select OK, the router.back() method is triggered and the jump is performed based on the parameters.
When the user clicks the back button, the custom confirmation dialog box is displayed, prompting the user to confirm their operation. If the user selects Cancel, the application stays on the current page. If the user selects OK, the **router.back()** API is triggered and the redirection is performed based on the parameters.
# UI Development (ArkTS-based Declarative Development Paradigm) Overview
Based on the ArkTS declarative development paradigm, the Ark development framework is a simplified, high-performance, and cross-device UI development framework. It provides the capabilities required for building the OpenHarmony application UI, including:
Powered by the ArkTS-based declarative development paradigm, ArkUI is a simplified, high-performance UI development framework for cross-device applications. It provides the capabilities required for building the OpenHarmony application UI, including:
- **ArkTS**
ArkTS is a UI development language extended based on TypeScript (TS) and is a superset of TS. Extension capabilities include various decorators, custom components, and UI description mechanisms. State data management provides clear page update and rendering processes and pipes through decorators with different functions. State management covers UI component states and application states. With these features, you are able to build an application-wide data update and UI rendering process. For details about the basic knowledge of ArkTS, see [Learning ArkTS] (../quick-start/arkts-get-started.md).
ArkTS is a UI development language. As a superset of TypeScript, ArkTS contains all TS features and added features, including a wide array of decorators, custom components, and the UI description mechanism. State data management provides clear page update and rendering processes and pipes through decorators with different functions. State management covers UI component states and application states. With these features, you are able to build an application-wide data update and UI rendering process. To learn more about ArkTS, see [Getting Started with ArkTS](../quick-start/arkts-get-started.md).
- **Layout**
The layout is a necessary element of the UI. It defines the position of a component on the UI. The ArkUI framework provides multiple layout modes. In addition to the basic linear layout, cascading layout, elastic layout, relative layout, and grid layout, the ArkUI framework also provides relatively complex lists, grids, and rotation.
The layout defines how components are laid out in the UI. ArkUI offers a diverse array of layouts. Besides the basic layouts – linear, stack, flex, relative, and grid, you also have access to the advanced list, grid, and swiper layouts.
- **Component**
Components are necessary elements of the UI and form the appearance of the UI. Components directly provided by the framework are called system components, and components defined by developers are called custom components. The built-in components of the system include buttons, option buttons, progress bars, and texts. Developers can set the rendering effect of built-in components in the system in chain invoking mode. You can combine system components to form custom components. In this way, page components are divided into independent UI units to implement independent creation, development, and reuse of different units on pages, making pages more engineering-oriented.
Components are essential elements of the UI, working together to shape the UI. They can be classified as built-in components – those directly provided by the ArkUI framework, and custom components – those defined by developers. The built-in components include buttons, radio buttons, progress indicators, and text. You can set the rendering effect of these components in method chaining mode. You can combine built-in components to form custom components. In this way, page components are divided into independent UI units to implement independent creation, development, and reuse of different units on pages, making pages more engineering-oriented.
- Page Routing and Component Navigation
- **Page routing and component navigation**
An application may contain multiple pages. Page routing can be used to switch between pages. Navigation between components may exist on a page, for example, a typical column. You can use the navigation component to implement navigation between components.
An application may contain a good many pages, and each page may come with multiple components. You can implement page routing to navigate users between pages and use navigation component to navigate them between components.
- **Graph**
- **Graphics**
The Ark development framework provides the display capability of multiple types of images and multiple customized drawing capabilities to meet developers' customized drawing requirements. It supports shape drawing, color filling, text drawing, deformation and cropping, and image embedding.
ArkUI offers diversified graphics capabilities, including capabilities to display images in various formats and custom drawing capabilities. By leveraging these capabilities, you can easily bring your custom drawing ideas into reality.
- **Animation**
Animation is one of the important elements of the UI. Excellent animation design can greatly improve user experience. The framework provides rich animation capabilities, including attribute animation, explicit animation, customized transition animation, and animation APIs in addition to built-in animation effects of components, developers can customize animation tracks by encapsulating physical models or invoking animation capability APIs.
Apart from animations embedded in components, ArkUI offers additional animation features: attribute animation, explicit animation, transition animation, and animation APIs. You can customize animation tracks by calling the provided animation APIs in addition to using the encapsulated physical models.
- Interaction Event
- **Interaction event**
Interaction events are necessary elements for the interaction between the UI and users. The Ark development framework provides multiple interaction events. In addition to common events such as touch events, mouse events, keyboard key events, and focus events, the Ark development framework also includes gesture events that are further recognized based on common events. The gesture event includes a single gesture such as a tap gesture, a touch and hold gesture, a drag gesture, a pinch gesture, a rotation gesture, a slide gesture, and a combined gesture event combined by using a single gesture event.
Interaction events are important for interactions between the UI and users. ArkUI allows users to interact with your application UI, with support for various universal events and gesture events. Universal events include touch events, mouse events, key events, and focus events. Gesture events accept single gestures (tap, long press, pan, pinch, rotation, and swipe), and a combination of gestures.
## Characteristics
## Highlights
- High development efficiency and good development experience
- Simple code: The UI is described in a way close to natural semantics, and you do not need to care about how the framework implements UI drawing and rendering.
- Data-driven UI change: Enables developers to focus on their own service logic processing. When the UI changes, developers do not need to compile the UI code for switching between different UIs. Instead, developers only need to compile the data that causes the UI change. The specific UI change is handed over to the framework.
- Good development experience: The GUI is also code, which improves the programming experience of developers.
- Simplified and efficient development
- Simple code: You can describe the UI in pseudo-natural language, without caring about how the framework implements UI drawing and rendering.
- Data-driven UI change: This allows you to better focus on your service logic processing. When the UI changes, you do not need to write code for switching between different UIs. Instead, you only need to write the data that causes the UI change and let the framework take over the rest.
- Improved development experience: Just code to get the UI developed.
- High Performance
- Declarative UI frontend and backend layering: The UI backend is constructed using the C++ language and provides basic components, layout, dynamic effects, interaction events, component status management, and rendering pipelines for the frontend.
- Language compiler and runtime optimization: unified bytecode, efficient FFI-Foreign Function Interface, AOT-Ahead Of Time, engine minimization, and type optimization.
- High performance
- Declarative UI frontend and backend layering: The UI backend, constructed using the C++ programming language, provides basic components, layout, animations, interaction events, component state management, and rendering pipelines for the frontend.
- Language compiler and runtime optimization: The productivity punch includes unified bytecode, efficient Foreign Function Interface (FFI), ahead-of-time (AOT), engine minimization, and type optimization.
- The ecosystem is easy to promote quickly.
Be able to leverage the mainstream language ecosystem to quickly promote the language. The language is relatively neutral and friendly. There are corresponding standard organizations that can gradually evolve.
- Promising ecosystem
ArkUI can gain traction with its relatively neutral and friendly programming language. It can tap on the ecosystems of mainstream languages ecosystem and pushed toward a steady revolutionary path with standards organizations.
## Architecture
Figure 1 Overall architecture
**Figure 1** Overall architecture
![arkui-arkts-framework](figures/arkui-arkts-framework.png)
......@@ -61,7 +61,7 @@ Based on the ArkTS declarative development paradigm, the Ark development framewo
Provides basic language specifications of the UI development paradigm, built-in UI components, layouts, and animations, and multiple state management mechanisms, with a wide array of APIs for you to call as required.
- **Language runtime**
When the Ark language is used, the UI normal form syntax parsing capability, cross-language invoking capability, and TS high-performance running environment are provided.
Provides the parsing capability for the UI paradigm syntax and allows for cross-language API calls for a high-performance operating environment of the TS language.
- **Declarative UI backend engine**
Provides UI rendering pipelines that are compatible with different development paradigms, multiple basic components, layout calculation, dynamic effects, and interaction events, with state management and drawing capabilities.
......@@ -69,27 +69,27 @@ Based on the ArkTS declarative development paradigm, the Ark development framewo
- **Render engine**
Provides efficient drawing capabilities, which enable rendering instructions collected by the rendering pipeline to be drawn to the screen.
- **Porting layer**
- **Platform adaptation layer**
Provides abstract APIs to connect to different systems, such as system rendering pipelines and lifecycle scheduling.
## Development process
## Development Process
When the UI development framework is used to develop applications, the following development process is involved: Developers can understand the UI development process of the entire application by referring to the ../quick-start/start-with-ets-stage.md example.
The table below lists the main tasks involved in UI development with ArkUI. You can familiarize yourself with the UI development process by [getting started with a simple project](../quick-start/start-with-ets-stage.md).
| Task | Introduction | Guide |
| Task | Description | Guide |
| ----------- | ----------------------------------- | ---------------------------------------- |
| Learning ArkTS | The basic syntax, state management, and rendering control scenarios of ArkTS are introduced. | - [Basic Syntax] (../quick-start/arkts-basic-syntax-overview.md)<br>- [Status Management] (../quick-start/arkts-state-management-overview.md)<br>- [Rendering Control] (../quick-start/arkts-rendering-control-overview.md)|
| Developing the Layout | This section describes several common layout modes and how to improve layout performance. | -&nbsp;[Common Layout](arkts-layout-development-overview.md)<br>-&nbsp;[Layout Performance](arkts-layout-development-performance-boost.md)|
| Add Component | This topic describes common built-in components, custom components, and GUI elements supported by APIs.| -&nbsp;[Common Components](arkts-common-components-button.md)<br>- [Customized Component] (../quick-start/arkts-create-custom-components.md)<br>-&nbsp;[Bubble and Menu](arkts-popup-and-menu-components-popup.md)|
| Setting Page Routes and Component Navigation| This topic describes how to set page routes and navigation between components. | -&nbsp;[Page Route] (arkts-routing.md)<br>-&nbsp;[Component Navigation] (arkts-navigation-navigation.md)|
| Display Chart | Describes how to display images, draw custom geometry, and draw custom graphics using the canvas. | -&nbsp; [image] (arkts-graphics-display.md)<br>-&nbsp;[geometric shape](arkts-geometric-shape-drawing.md)<br>-&nbsp;[Canvas](arkts-drawing-customization-on-canvas.md)|
| Using Animation | This topic describes the typical scenarios of using animations on components and pages. | -&nbsp;[Animation on the page](arkts-layout-update-animation.md)<br>-&nbsp; [animation between pages] (arkts-zoom-animation.md)|
| Binding Events | This topic describes the basic concepts of events and how to use common events and gesture events. | -&nbsp;[Common Event](arkts-common-events-touch-screen-event.md)<br>-&nbsp;[Gesture event](arkts-gesture-events-binding.md)|
| Get started with ArkTS | Learn the basic syntax, state management, and rendering control scenarios of ArkTS. | - [Basic Syntax Overview](../quick-start/arkts-basic-syntax-overview.md)<br>- [State Management](../quick-start/arkts-state-management-overview.md)<br>- [Rendering Control](../quick-start/arkts-rendering-control-overview.md) |
| Develop the layout | Understand the common layouts and how to improve layout performance. | - [Layout Overview](arkts-layout-development-overview.md)<br>- [Improving Layout Performance](arkts-layout-development-performance-boost.md)|
| Add components | Learn the usage of common built-in components, custom components, and GUI elements supported by APIs.| - [Common Components](arkts-common-components-button.md)<br>- [Custom Components](../quick-start/arkts-create-custom-components.md)<br>- [Popup and Menu](arkts-popup-and-menu-components-popup.md)|
| Set page routing and component navigation| Learn how to set page routes and navigation between components. | - [Page Routing](arkts-routing.md)<br>- [Navigation](arkts-navigation-navigation.md)|
| Use graphics | Understand how to display images, draw custom geometry, and make custom graphics on the canvas. | - [Displaying Images](arkts-graphics-display.md)<br>- [Drawing Geometric Shapes](arkts-geometric-shape-drawing.md)<br>- [Drawing Custom Graphics Using the Canvas](arkts-drawing-customization-on-canvas.md) |
| Apply animations | Learn the typical scenarios of applying animations on components and pages. | - [Animation Within a Page](arkts-layout-update-animation.md)<br>- [Animation Between Pages](arkts-zoom-animation.md)|
| Bind events | Learn the basic concepts of events and how to use common events and gesture events. | - [Universal Events](arkts-common-events-touch-screen-event.md)<br>- [Gesture Events](arkts-gesture-events-binding.md)|
## Samples
##
For details about the declarative development paradigm based on ArkTS, see the following example:
[ArkTS component set] (https://gitee.com/openharmony/applications_app_samples/tree/master/code/UI/ArkTsComponentClollection/ComponentCollection): a set of components, common methods, animations, and global methods.
......@@ -34,28 +34,28 @@ Call the **animate** method to obtain an animation object, which supports animat
```js
/* xxx.js */
export default {
data: {
animation: '',
},
onInit() {
},
onShow() {
var options = {
duration: 1500,
};
var frames = [
{
width:200,height:200,
},
{
width:300,height:300,
}
];
this.animation = this.$element('content').animate(frames, options); // Obtain the animation object.
},
Show() {
this.animation.play();
}
data: {
animation: '',
options: {},
frames: {}
},
onInit() {
this.options = {
duration: 1500,
};
this.frames = [
{
width: 200, height: 200,
},
{
width: 300, height: 300,
}
];
},
Show() {
this.animation = this.$element('content').animate(this.frames, this.options); // Obtain the animation object.
this.animation.play();
}
}
```
......@@ -172,297 +172,52 @@ Set the animation attributes by using the **options** parameter.
```js
/* xxx.js */
export default {
data: {
animation: '',
},
onInit() {
},
onShow() {
var options = {
duration: 1500,
easing: 'ease-in',
delay: 5,
iterations: 2,
direction: 'normal',
};
var frames = [
{
transform: {
translate: '-150px -0px'
}
},
{
transform: {
translate: '150px 0px'
}
}
];
this.animation = this.$element('content').animate(frames, options);
},
Show() {
this.animation.play();
}
}
```
![en-us_image_0000001222967796](figures/en-us_image_0000001222967796.gif)
> **NOTE**
>
> **direction**: mode of playing the animation.
>
> **normal**: plays the animation in forward loop mode.
>
> **reverse**: plays the animation in reverse loop mode.
>
> **alternate**: plays the animation in alternating loop mode. When the animation is played for an odd number of times, the playback is in forward direction. When the animation is played for an even number of times, the playback is in reverse direction.
>
> **alternate-reverse**: plays the animation in reverse alternating loop mode. When the animation is played for an odd number of times, the playback is in reverse direction. When the animation is played for an even number of times, the playback is in forward direction.
## Adding an Event and Calling a Method
Animation objects support animation events and methods. You can achieve the intended animation by adding start and cancel events and calling the play, pause, rewind, and stop methods.
```html
<!-- xxx.hml -->
<div class="container">
<div id="content" style="width: 350px;height: 350px;margin-top: 100px;background: linear-gradient(pink, purple);">
</div>
<div class="row">
<button type="capsule" value="play" onclick="playAnimation"></button>
<button type="capsule" value="pause" onclick="pauseAnimation"></button>
</div>
<div class="row1">
<button type="capsule" value="reverse" onclick="reverseAnimation"></button>
<button type="capsule" value="cancel" onclick="cancelAnimation"></button>
</div>
</div>
```
```css
/* xxx.css */
.container {
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
button{
width: 200px;
}
.row{
width: 65%;
height: 100px;
align-items: center;
justify-content: space-between;
margin-top: 40px;
position: fixed;
top: 65%;
left: 120px;
}
.row1{
width: 65%;
height: 100px;
align-items: center;
justify-content: space-between;
margin-top: 30px;
position: fixed;
top: 75%;
left: 120px;
}
```
```js
// xxx.js
export default {
data: {
animation: '',
options: {},
frames: {}
},
onShow() {
var options = {
onInit() {
this.options = {
duration: 1500,
easing:'ease-in',
delay:5,
direction:'normal',
iterations:2
easing: 'ease-in',
delay: 5,
iterations: 2,
direction: 'normal',
};
var frames = [
this.frames = [
{
transform: {
translate: '-150px -0px'
},
opacity: 0.1,
offset: 0.0,
width: 200,
height: 200,
}
},
{
transform: {
translate: '150px 0px'
},
opacity: 1.0,
offset: 1.0,
width: 300,
height: 300,
}
}
];
this.animation = this.$element('content').animate(frames, options);
this.animation.onstart = function() {
console.info('animation start')
} // Add a start event.
this.animation.onrepeat = function() {
console.info('animation repeated')
} // Add a repeat event.
this.animation.oncancel = function() {
console.info('animation canceled')
} // Add a cancel event.
this.animation.onfinish = function() {
console.info('animation finish')
} // Add a finish event.
},
playAnimation() {
this.animation.play() // Start this animation.
},
pauseAnimation() {
this.animation.pause() // Pause this animation.
},
reverseAnimation() {
this.animation.reverse() // Reverse this animation.
},
cancelAnimation() {
this.animation.cancel() // Cancel this animation.
Show() {
this.animation = this.$element('content').animate(this.frames, this.options);
this.animation.play();
}
}
```
![en-us_image_0000001220635011](figures/en-us_image_0000001220635011.gif)
Change the animation status by changing the **playState** attribute.
```html
<!-- xxx.hml -->
<div class="container">
<div id="content" style="width: 350px;height: 350px;margin-top: 100px;background: linear-gradient(pink, purple);">
</div>
<div class="row">
<button type="capsule" value="{{state}}" onclick="playStateClick"></button>
</div>
<div class="row1">
<button type="capsule" value="{{state1}}" onclick="playStateClick1"></button>
</div>
</div>
```
![en-us_image_0000001222967796](figures/en-us_image_0000001222967796.gif)
```css
/* xxx.css */
.container {
flex-direction: column;
align-items: center;
justify-content: center;
}
button{
width: 200px;
}
.row{
width: 65%;
height: 100px;
align-items: center;
justify-content: space-between;
margin-top: 50px;
margin-left: 260px;
position: fixed;
top: 65%;
}
.row1{
width: 65%;
height: 100px;
align-items: center;
justify-content: space-between;
margin-top: 50px;
margin-left: 260px;
position: fixed;
top: 75%;
}
```
> **NOTE**
>
> **direction**: mode of playing the animation.
>
> **normal**: plays the animation in forward loop mode.
>
> **reverse**: plays the animation in reverse loop mode.
>
> **alternate**: plays the animation in alternating loop mode. When the animation is played for an odd number of times, the playback is in forward direction. When the animation is played for an even number of times, the playback is in reverse direction.
>
> **alternate-reverse**: plays the animation in reverse alternating loop mode. When the animation is played for an odd number of times, the playback is in reverse direction. When the animation is played for an even number of times, the playback is in forward direction.
```js
// xxx.js
import promptAction from '@ohos.promptAction';
export default {
data: {
animation: '',
state:'play',
state1:'play'
},
onInit() {
},
onShow() {
var options = {
duration: 1500,
easing:'ease-in',
elay:5,
direction:'normal',
iterations:2,
};
var frames = [
{
transform: {
translate: '-150px -0px'
},
opacity: 0.1,
offset: 0.0,
width: 200,
height: 200,
},
{
transform: {
translate: '150px 0px'
},
opacity: 1.0,
offset: 1.0,
width: 300,
height: 300,
}
];
this.animation = this.$element('content').animate(frames, options);
this.animation.onstart = function(){
promptAction.showToast({
message: "start"
});
};
this.animation.onrepeat = function(){
promptAction.showToast({
message: " repeated"
});
};
this.animation.onfinish = function(){
promptAction.showToast({
message: " finished"
});
};
},
playStateClick(){
if(this.animation.playState != 'running'){
this.animation.playState = 'running';// Set playState to running to run the animation.
this.state = 'pause'
}else{
this.animation.playState = 'paused';// Set playState to paused to pause the animation.
this.state = 'play'
}
},
playStateClick1(){
if(this.animation.playState != 'running'){
this.animation.playState = 'running';
this.state1 = 'finish'
}else{
this.animation.playState = 'finished';// Set playState to finished to stop the animation.
this.state1 = 'play'
}
}
}
```
![en-us_image_0000001267607921](figures/en-us_image_0000001267607921.gif)
......@@ -156,7 +156,7 @@ button{
```js
// xxx.js
import animator from '@ohos.animator';
import prompt from '@system.prompt';
import promptAction from '@ohos.promptAction';
export default {
data: {
scaleVal:1,
......@@ -178,7 +178,7 @@ export default {
var _this= this;
// Add an animation repeat event.
this.animation.onrepeat = function() {
prompt.showToast({
promptAction.showToast({
message: 'repeat'
});
var repeatoptions = {
......@@ -220,7 +220,7 @@ export default {
var _this= this;
// Add an animation completion event.
this.animation.onfinish = function() {
prompt.showToast({
promptAction.showToast({
message: 'finish'
})
};
......
......@@ -51,7 +51,7 @@ Create a square and rotate it by 90 degrees to form a rhombus. Cover the lower p
}
.door{
width: 100px;
height: 150px;
height: 135px;
background-color: #1033d9;
transform: translate(150px,-137px);
}
......@@ -198,111 +198,111 @@ Set the rotation center around an element in different transform-origin position
```css
/* xxx.css */
.container {
flex-direction: column;
background-color:#F1F3F5;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
flex-direction: column;
background-color:#F1F3F5;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.rect {
width: 100px;
height: 100px;
animation: rotate 3s infinite;
margin-left: 100px;
width: 100px;
height: 100px;
animation: rotate 3s infinite;
margin-left: 30px;
}
.rect1 {
background-color: #f76160;
background-color: #f76160;
}
.rect2 {
background-color: #60f76f;
/* Change the origin position.*/
transform-origin: 10% 10px;
background-color: #60f76f;
/* Change the origin position.*/
transform-origin: 10% 10px;
}
.rect3 {
background-color: #6081f7;
/* Change the origin position.*/
transform-origin: right bottom;
background-color: #6081f7;
/* Change the origin position.*/
transform-origin: right bottom;
}
@keyframes rotate {
from {
transform: rotate(0deg)
}
to {
transform: rotate(360deg);
}
from {
transform: rotate(0deg)
}
to {
transform: rotate(360deg);
}
}
/* 3D sample style */
.rotate3d {
margin-top: 150px;
flex-direction: column;
background-color:#F1F3F5;
display: flex;
align-items: center;
width: 80%;
height: 600px;
border-radius: 300px;
border: 1px solid #ec0808;
margin-top: 150px;
flex-direction: column;
background-color:#F1F3F5;
display: flex;
align-items: center;
width: 80%;
height: 600px;
border-radius: 300px;
border: 1px solid #ec0808;
}
.content {
padding-top: 150px;
display: flex;
align-items: center;
justify-content: center;
padding-top: 150px;
display: flex;
align-items: center;
justify-content: center;
}
/* Use react4 and react5 to shape eyes. */
.rect4 {
width: 100px;
height: 100px;
animation: rotate3d1 1000ms infinite;
background: linear-gradient(#e6c4ec, #be15d9)
width: 100px;
height: 100px;
animation: rotate3d1 1000ms infinite;
background-color: darkmagenta;
}
.rect5 {
width: 100px;
height: 100px;
animation: rotate3d1 1000ms infinite;
margin-left: 100px;
background: linear-gradient(#e6c4ec, #be15d9)
width: 100px;
height: 100px;
animation: rotate3d1 1000ms infinite;
margin-left: 100px;
background-color: darkmagenta;
}
.mouse {
margin-top: 150px;
width: 200px;
height: 100px;
border-radius: 50px;
border: 1px solid #e70303;
animation: rotate3d2 1000ms infinite;
margin-top: 150px;
width: 200px;
height: 100px;
border-radius: 50px;
border: 1px solid #e70303;
animation: rotate3d2 1000ms infinite;
}
/* Eye animation */
@keyframes rotate3d1 {
0% {
transform:rotate3d(0,0,0,0deg)
}
50% {
transform:rotate3d(20,20,20,360deg);
}
100% {
transform:rotate3d(0,0,0,0deg);
}
0% {
transform:rotate3d(0,0,0,0deg)
}
50% {
transform:rotate3d(20,20,20,360deg);
}
100% {
transform:rotate3d(0,0,0,0deg);
}
}
/* Mouth animation */
@keyframes rotate3d2 {
0% {
transform:rotate3d(0,0,0,0deg)
}
33% {
transform:rotate3d(0,0,10,30deg);
}
66% {
transform:rotate3d(0,0,10,-30deg);
}
100% {
transform:rotate3d(0,0,0,0deg);
}
0% {
transform:rotate3d(0,0,0,0deg)
}
33% {
transform:rotate3d(0,0,10,30deg);
}
66% {
transform:rotate3d(0,0,10,-30deg);
}
100% {
transform:rotate3d(0,0,0,0deg);
}
}
```
![en-us_image_0000001222807776](figures/en-us_image_0000001222807776.gif)
![en-us_image_0000001220316305](figures/en-us_image_0000001220316305.gif)
> **NOTE**
>
......@@ -333,90 +333,89 @@ Set the scaling values for the x-axis, y-axis, and z-axis in **scale3d** to impl
```css
/* xxx.css */
.container {
flex-direction: column;
background-color:#F1F3F5;
width: 100%;
position: relative;
flex-direction: column;
background-color:#F1F3F5;
width: 100%;
position: relative;
}
.circle{
margin-top: 400px;
margin-left: 40%;
width: 100px;
height: 100px;
border-radius: 50px;
background:linear-gradient(#dcaec1, #d3a8e3);
z-index: 1; position: absolute;
margin-top: 400px;
margin-left: 40%;
width: 100px;
height: 100px;
border-radius: 50px;
background-color: mediumpurple;
z-index: 1; position: absolute;
}
.ripple{
margin-top: 400px;
margin-left: 40%;
position: absolute; z-index: 0;
width: 100px;
height: 100px;
border-radius: 50px;
background:linear-gradient(#dcaec1,#d3a8e3);
animation: ripple 5s infinite;
margin-top: 400px;
margin-left: 40%;
position: absolute; z-index: 0;
width: 100px;
height: 100px;
border-radius: 50px;
background-color: blueviolet;
animation: ripple 5s infinite;
}
/* Set different animation durations for different components. */
.ripple2{
animation-duration: 2.5s;
animation-duration: 2.5s;
}
@keyframes ripple{
0%{
transform: scale(1);
opacity: 0.5;
}
50%{
transform: scale(3);
opacity: 0;
}
100%{
transform: scale(1);
opacity: 0.5;
}
0%{
transform: scale(1);
opacity: 0.5;
}
50%{
transform: scale(3);
opacity: 0;
}
100%{
transform: scale(1);
opacity: 0.5;
}
}
text{
color: white;
text-align: center;
height: 100%;
width: 100%;
color: white;
text-align: center;
height: 100%;
width: 100%;
}
.content {
margin-top: 700px;
margin-left: 33%;
width: 200px;
height: 100px;
animation:rubberBand 1s infinite;
/* Set the gradient.*/
background:linear-gradient(#e276aa,#ec0d66);
position: absolute;
margin-top: 700px;
margin-left: 33%;
width: 200px;
height: 100px;
animation:rubberBand 1s infinite;
background-color: darkmagenta;
position: absolute;
}
@keyframes rubberBand {
0% {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1.1);
}
40% {
transform: scale3d(0.75, 1.25, 1.2);
}
50% {
transform: scale3d(1.15, 0.85, 1.3);
}
65% {
transform: scale3d(.95, 1.05, 1.2);
}
75% {
transform: scale3d(1.05, .95, 1.1);
}
100%{
transform: scale3d(1, 1, 1);
}
0% {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1.1);
}
40% {
transform: scale3d(0.75, 1.25, 1.2);
}
50% {
transform: scale3d(1.15, 0.85, 1.3);
}
65% {
transform: scale3d(.95, 1.05, 1.2);
}
75% {
transform: scale3d(1.05, .95, 1.1);
}
100%{
transform: scale3d(1, 1, 1);
}
}
```
![en-us_image_0000001267887837](figures/en-us_image_0000001267887837.gif)
![en-us_image_0000001220396251](figures/en-us_image_0000001220396251.gif)
> **NOTE**
>
......@@ -465,7 +464,7 @@ The matrix attribute defines a transformation matrix with six input parameters:
}
```
![en-us_image_0000001267767853](figures/en-us_image_0000001267767853.gif)
![en-us_image_0000001174756580](figures/en-us_image_0000001174756580.gif)
## Integrating transform Attributes
......@@ -486,96 +485,96 @@ You can set multiple **transform** attributes at the same time to apply differen
```css
/* xxx.css */
.container{
width: 100%;
height: 100%;
flex-direction:column;
background-color:#F1F3F5;
padding:50px;
width: 100%;
height: 100%;
flex-direction:column;
background-color:#F1F3F5;
padding:50px;
}
.rect1{
width: 100px;
height: 100px;
background:linear-gradient(#e77070,#ee0202);
animation: change1 3s infinite forwards;
width: 100px;
height: 100px;
background-color: red;
animation: change1 3s infinite forwards;
}
.rect2{
margin-top: 50px;
width: 100px;
height: 100px;
background:linear-gradient(#95a6e8, #2739de);
animation: change2 3s infinite forwards;
margin-top: 50px;
width: 100px;
height: 100px;
background-color: darkblue;
animation: change2 3s infinite forwards;
}
.rect3{
margin-top: 50px;
width: 100px;
height: 100px;
background:linear-gradient(#142ee2, #8cb1e5);
animation: change3 3s infinite;
margin-top: 50px;
width: 100px;
height: 100px;
background-color: darkblue;
animation: change3 3s infinite;
}
.rect4{
align-self: center;
margin-left: 50px;
margin-top: 200px;
width: 100px;
height: 100px;
background:linear-gradient(#e2a8df, #9c67d4,#8245d9,#e251c3);
animation: change4 3s infinite;
align-self: center;
margin-left: 50px;
margin-top: 200px;
width: 100px;
height: 100px;
background-color: darkmagenta;
animation: change4 3s infinite;
}
.rect5{
margin-top: 300px;
width: 100px;
height: 100px;
background:linear-gradient(#e7ded7, #486ccd, #94b4d2);
animation: change5 3s infinite;
margin-top: 300px;
width: 100px;
height: 100px;
background-color: cadetblue;
animation: change5 3s infinite;
}
/* Use change1 and change2 for comparison. */
@keyframes change1{
0%{
transform: translate(0,0); transform: rotate(0deg)
}
100%{
transform: translate(0,500px);
transform: rotate(360deg)
}
0%{
transform: translate(0,0); transform: rotate(0deg)
}
100%{
transform: translate(0,500px);
transform: rotate(360deg)
}
}
/*change2 and change3 compare the animation effects with different attribute sequences.*/
@keyframes change2{
0%{
transform:translate(0,0) rotate(0deg) ;
}
100%{
transform: translate(300px,0) rotate(360deg);
}
0%{
transform:translate(0,0) rotate(0deg) ;
}
100%{
transform: translate(300px,0) rotate(360deg);
}
}
@keyframes change3{
0%{
transform:rotate(0deg) translate(0,0);
}
100%{
transform:rotate(360deg) translate(300px,0);
}
0%{
transform:rotate(0deg) translate(0,0);
}
100%{
transform:rotate(360deg) translate(300px,0);
}
}
/* Where the attribute values do not match. */
@keyframes change4{
0%{
transform: scale(0.5);
}
100%{
transform:scale(2) rotate(45deg);
}
0%{
transform: scale(0.5);
}
100%{
transform:scale(2) rotate(45deg);
}
}
/* Multi-attribute format */
@keyframes change5{
0%{
transform:scale(0) translate(0,0) rotate(0);
}
100%{
transform: scale(1.5) rotate(360deg) translate(200px,0);
}
0%{
transform:scale(0) translate(0,0) rotate(0);
}
100%{
transform: scale(1.5) rotate(360deg) translate(200px,0);
}
}
```
![en-us_image_0000001223127712](figures/en-us_image_0000001223127712.gif)
![en-us_image_0000001220554911](figures/en-us_image_0000001220554911.gif)
> **NOTE**
>
......
......@@ -51,61 +51,9 @@ Create a **&lt;tabs&gt;** component in the .hml file under **pages/index**.
![en-us_image_0000001223287676](figures/en-us_image_0000001223287676.gif)
## Setting the Tabs Orientation
By default, the active tab of a **&lt;tabs&gt;** component is the one with the specified **index**. To show the **&lt;tabs&gt;** vertically, set the **vertical** attribute to **true**.
```html
<!-- xxx.hml -->
<div class="container" style="background-color:#F1F3F5;">
<tabs index="1" vertical="true">
<tab-bar >
<text>item1</text>
<text style="margin-top: 50px;">item2</text>
</tab-bar>
<tab-content>
<div>
<image src="common/images/bg-tv.jpg" style="object-fit: contain;"> </image>
</div>
<div>
<image src="common/images/img1.jpg" style="object-fit: contain;"> </image>
</div>
</tab-content>
</tabs>
</div>
```
![en-us_image_0000001222967756](figures/en-us_image_0000001222967756.gif)
Set the **mode** attribute to enable the child components of the **&lt;tab-bar&gt;** to be evenly distributed. Set the **scrollable** attribute to disable scrolling of the **&lt;tab-content&gt;**.
```html
<!-- xxx.hml -->
<div class="container" style="background-color:#F1F3F5;">
<tabs style="margin-top: 30px;">
<tab-bar mode="fixed">
<text>item1</text>
<text>item2</text>
</tab-bar>
<tab-content scrollable="false">
<div>
<image src="common/images/bg-tv.jpg" style="object-fit: contain;"> </image>
</div>
<div>
<image src="common/images/img2.jpg" style="object-fit: contain;"> </image>
</div>
</tab-content>
</tabs>
</div>
```
![en-us_image_0000001267647857](figures/en-us_image_0000001267647857.gif)
## Setting Styles
Set the background color, border, and tab-content layout of the **&lt;tabs&gt;** component.
```html
<!-- xxx.hml -->
<div class="container">
......
......@@ -732,7 +732,7 @@ export default {
}
```
![en-us_image_0000001232003008](figures/en-us_image_0000001232003008.gif)
![en-us_image_0000001218279600](figures/en-us_image_0000001218279600.gif)
> **NOTE**
> - Unlike the **transform()** function, the **setTransform()** function resets the existing transformation matrix and creates a transformation matrix even if it uses the same parameters.
......
......@@ -269,8 +269,7 @@ Use the **&lt;dialog&gt;** component to implement a schedule. When the dialog bo
```js
// xxx.js
var info = null;
import prompt from '@system.prompt';
import router from '@system.router';
import promptAction from '@ohos.promptAction';
export default {
data: {
curYear:'',
......@@ -293,7 +292,7 @@ export default {
this.$element('datedialog').show()
},
canceldialog(e) {
prompt.showToast({
promptAction.showToast({
message: 'Event setting canceled.'
})
},
......@@ -302,7 +301,7 @@ export default {
},
cancelschedule(e) {
this.$element('datedialog').close()
prompt.showToast({
promptAction.showToast({
message: 'Event setting canceled.'
})
},
......
......@@ -12,7 +12,7 @@ Create a **\<grid-container>** component in the .hml file under **pages/index**
```html
<!-- index.hml -->
<div class="container">
<grid-container id="mygrid" columns="5" gutter="20px" style="background-color: pink;">
<grid-container id="mygrid" gutter="20px" style="background-color: pink;">
<grid-row style="height:100px;justify-content:space-around;width: 80%;background-color: #f67002;margin-left:
10%;"></grid-row>
<grid-row style="height:300px;justify-content:space-around;background-color: #ffcf00;width: 100%;"></grid-row>
......@@ -27,8 +27,7 @@ Create a **\<grid-container>** component in the .hml file under **pages/index**
.container{
flex-direction: column;
background-color: #F1F3F5;
width: 100%;
height: 100%;
margin-top: 500px;
justify-content: center;
align-items: center;
}
......@@ -49,7 +48,7 @@ Touch the **\<grid-container>** component to call the **getColumns**, **getColum
```html
<!-- index.hml -->
<div class="container">
<grid-container id="mygrid" columns="6" gutter="20px" style="background-color: pink;padding-top: 100px;"
<grid-container id="mygrid" gutter="20px" style="background-color: pink;padding-top: 100px;"
onclick="getColumns" onlongpress="getSizeType">
<grid-row style="height:100px;justify-content:space-around;background-color: #4cedf3;width: 20%;margin-left:
40%;"></grid-row>
......@@ -68,8 +67,7 @@ Touch the **\<grid-container>** component to call the **getColumns**, **getColum
.container{
flex-direction: column;
background-color: #F1F3F5;
width: 100%;
height: 100%;
margin-top: 400px;
justify-content: center;
align-items: center;
}
......@@ -108,7 +106,7 @@ export default {
}
```
![en-us_image_0000001231843088](figures/en-us_image_0000001231843088.gif)
![en-us_image_0000001227135613](figures/en-us_image_0000001227135613.gif)
## Adding \<grid-col>
......@@ -164,7 +162,7 @@ After adding a **\<grid-row>** child component to **\<grid-container>**, add a *
text{
color: white;
font-size: 40px;
}
```
![en-us_image_0000001231683124](figures/en-us_image_0000001231683124.png)
......@@ -219,7 +217,7 @@ text{
```js
// index.js
import prompt from '@system.prompt';
import promptAction from '@ohos.promptAction';
export default {
data:{
list:[
......@@ -230,7 +228,7 @@ export default {
fresh:false
},
refresh(e) {
prompt.showToast({
promptAction.showToast({
message: 'refreshing'
})
var that = this;
......@@ -238,7 +236,7 @@ export default {
setTimeout(function () {
that.fresh = false;
that.list.unshift({src: 'common/images/4.png',id:'4'});
prompt.showToast({
promptAction.showToast({
message: 'succeed'
})
}, 2000)
......
......@@ -285,7 +285,7 @@ button{
```js
// index.js
import prompt from '@system.prompt';
import promptAction from '@ohos.promptAction';
export default {
data: {
rev:false,
......@@ -317,7 +317,7 @@ export default {
this.$element('img').resume()
},
getimgstate(e) {
prompt.showToast({
promptAction.showToast({
message: 'Current state:' + this.$element('img').getState()
})
},
......
......@@ -12,7 +12,7 @@ Create a **&lt;marquee&gt;** component in the .hml file under **pages/index**.
```html
<!-- xxx.hml -->
<div class="container">
<marquee style="width: 100%;height: 80px; color: #ffffff; background-color: #0820ef;padding-left: 200px;">This is a marquee.</marquee>
<marquee style="width: 100%;height: 80px; color: #ffffff; background-color: #0820ef;padding-left: 200px;">It's a racing lamp.</marquee>
</div>
```
......
......@@ -179,15 +179,15 @@ Click the **&lt;toggle&gt;** component to change the text color and select the *
```html
<!-- xxx.hml-->
<div class="container">
<div class="contentToggle">
<toggle class="toggle" for="{{item in togglesList}}" onclick="toggleClick({{$idx}})" checked="{{item.checked}}">{{item.name}}</toggle>
</div>
<text class="size" style="color: {{color}};">width:{{width}},height:{{height}}</text>
<div style="width: {{width}}'px';height: {{height}}px;background:linear-gradient(to right,#FF0000,#0000FF);"></div>
<text id="menuId" class="text">change size</text>
<menu onselected="select" oncancel="cancel" target="menuId">
<option value="{{item.value}}" for="item in optionList">{{item.text}}</option>
</menu>
<div class="contentToggle">
<toggle class="toggle" for="{{item in togglesList}}" onclick="toggleClick({{$idx}})" checked="{{item.checked}}">{{item.name}}</toggle>
</div>
<text class="size" style="color: {{color}};">width:{{width}},height:{{height}}</text>
<div style="width: {{width}}px;height: {{height}}px; background-color: cornflowerblue;"></div>
<text id="menuId" class="text">change size</text>
<menu onselected="select" oncancel="cancel" target="menuId">
<option value="{{item.value}}" for="item in optionList">{{item.text}}</option>
</menu>
</div>
```
......@@ -242,7 +242,6 @@ option{
```js
// xxx.js
import promptAction from '@ohos.promptAction';
export default {
data:{
fresh: false,
......@@ -277,4 +276,4 @@ export default {
}
```
![en-us_image_0000001276003485](figures/en-us_image_0000001276003485.gif)
![en-us_image_0000001226815403](figures/en-us_image_0000001226815403.gif)
......@@ -33,7 +33,7 @@ rating {
}
```
![en-us_image_0000001231843116](figures/en-us_image_0000001231843116.gif)
![en-us_image_0000001227701031](figures/en-us_image_0000001227701031.gif)
## Setting the Rating Level
......@@ -66,7 +66,7 @@ rating {
}
```
![en-us_image_0000001232003012](figures/en-us_image_0000001232003012.gif)
![en-us_image_0000001227422709](figures/en-us_image_0000001227422709.gif)
## Setting the Rating Style
......@@ -114,7 +114,7 @@ export default {
}
```
![en-us_image_0000001275803173](figures/en-us_image_0000001275803173.gif)
![en-us_image_0000001178685854](figures/en-us_image_0000001178685854.gif)
> **NOTE**
> - You must set **star-background**, **star-secondary**, and **star-foreground**. Otherwise, the grey rating star applies, indicating that the image source is incorrectly set.
......@@ -154,17 +154,17 @@ rating {
```js
// xxx.js
import prompt from '@system.prompt';
import promptAction from '@ohos.promptAction';
export default {
showrating(e) {
prompt.showToast({
promptAction.showToast({
message:'Current Rating' + e.rating
})
}
}
```
![en-us_image_0000001276003525](figures/en-us_image_0000001276003525.gif)
![en-us_image_0000001181823160](figures/en-us_image_0000001181823160.gif)
## Example Scenario
......@@ -256,4 +256,4 @@ export default {
}
```
![en-us_image_0000001275923005](figures/en-us_image_0000001275923005.gif)
![en-us_image_0000001224086459](figures/en-us_image_0000001224086459.gif)
......@@ -114,7 +114,7 @@ text{
}
```
![en-us_image_0000001275923021](figures/en-us_image_0000001275923021.gif)
![en-us_image_0000001181655292](figures/en-us_image_0000001181655292.gif)
> **NOTE**
> - The **digital** attribute takes effect only when the **indicator** attribute is set to **true**.
......@@ -132,17 +132,17 @@ Set the width and height of the **&lt;swiper&gt;** component, the indicator's si
```html
<!-- xxx.hml-->
<div class="container">
<swiper index="1" autoplay="true" interval="2000" duration="500" >
<div class="item" style="background: linear-gradient(to right,#806dd9,#5d44ea,#2eb9d5)">
<text>item1</text>
</div>
<div class="item" style="background: linear-gradient( to right,#2eb9d5,#0e7db4,#2673d9)">
<text>item2</text>
</div>
<div class="item" style="background: linear-gradient( to right,#2673d9,#0c89af,#806dd9)">
<text>item3</text>
</div>
</swiper>
<swiper index="1" autoplay="true" interval="2000" duration="500" >
<div class="item" style="background-color: bisque;">
<text>item1</text>
</div>
<div class="item" style="background-color: darkkhaki;">
<text>item2</text>
</div>
<div class="item" style="background-color: cadetblue;">
<text>item3</text>
</div>
</swiper>
</div>
```
......@@ -180,7 +180,7 @@ text{
}
```
![en-us_image_0000001275803189](figures/en-us_image_0000001275803189.gif)
![en-us_image_0000001226896657](figures/en-us_image_0000001226896657.gif)
## Binding Events
......
......@@ -108,10 +108,6 @@ Set the **position** style for the **&lt;toolbar&gt;** component and set the fon
toolbar-item{
font-size: 35px;
}
.toolbarActive{
color: red;
background-color: #daebef;
}
```
......@@ -187,9 +183,8 @@ Use the **for** loop to create a **&lt;toolbar-item&gt;** component and bind a c
<div class="container">
<image src="{{imgList[active]}}"></image>
<toolbar style="position: fixed;bottom: 5%;width: 100%;background-color: #F1F3F5;">
<toolbar-item value="{{ item.option}}" icon="{{item.icon}}" style="color: {{active == $idx?'red':'black'}};background-color: {{active
== $idx?'#dbe7f1':'#F1F3F5'}};" for="{{item in itemList}}" onclick="itemClick({{$idx}})"></toolbar-item>
</toolbar>
<toolbar-item value="{{ item.option}}" icon="{{item.icon}}" style="color: {{active == $idx?'red':'black'}};background-color: {{active== $idx?'#dbe7f1':'#F1F3F5'}};" for="{{item in itemList}}" onclick="itemClick({{$idx}})"></toolbar-item>
</toolbar>
</div>
```
......@@ -211,7 +206,6 @@ toolbar-item{
```js
// xxx.js
import prompt from '@system.prompt';
export default {
data:{
active: 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册