提交 770a2fc6 编写于 作者: S sienna1128 提交者: Gitee

Merge branch 'master' of gitee.com:openharmony/docs into gesture

Signed-off-by: Nsienna1128 <lixiaoyan45@huawei.com>
......@@ -317,6 +317,7 @@ zh-cn/application-dev/reference/apis/js-apis-system-parameter.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-thermal.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-update.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-usb.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-colorSpaceManager.mdd @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-vibrator.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-appAccount.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-distributed-account.md @zengyawen
......
......@@ -4,7 +4,7 @@
The **distributedDataObject** module provides APIs to implement data collaboration of the same application across multiple devices. In addition, the devices that form a Super Device can listen for object status and data changes with each other.
For example, when the data of the a distributed data object is added, deleted, or modified for application A on device 1, application A on device 2 can obtain the updated data. In addition, device 2 can listen for data changes and online/offline of the data objects on device 1.
For example, when the data of a distributed data object is added, deleted, or modified for application A on device 1, application A on device 2 can obtain the updated data. In addition, device 2 can listen for data changes and online/offline of the data objects on device 1.
## Available APIs
......@@ -18,7 +18,7 @@ Call **createDistributedObject()** to create a distributed data object instance.
**Table 1** API for creating a distributed data object instance
| Package| API| Description|
| -------- | -------- | -------- |
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.<br>- **source**: attributes of the **distributedObject** set.<br>- **DistributedObject**: returns the distributed object created.|
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.<br>- **source**: attributes of the distributed data object to set.<br>- **DistributedObject**: returns the distributed data object created. |
### Generating a Session ID
......@@ -29,14 +29,14 @@ Call **genSessionId()** to generate a session ID randomly. The generated session
| -------- | -------- | -------- |
| ohos.data.distributedDataObject| genSessionId(): string | Generates a session ID, which can be used as the session ID of a distributed data object.|
### Setting a SessionID for a Distributed Data Object
### Setting a Session ID for a Distributed Data Object
Call **setSessionId()** to set a session ID for a distributed data object. The session ID is a unique identifier for one collaboration across devices. The distributed data objects to be synchronized must be associated with the same session ID.
**Table 3** API for setting a session ID
| Class| API| Description|
| -------- | -------- | -------- |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for a distributed data object.<br>**sessionId**: session ID of a distributed object in a trusted network. To remove a distributed data object from the network, set this parameter to "" or leave it empty.|
| DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for a distributed data object.<br>**sessionId**: session ID of a distributed data object in a trusted network. To remove a distributed data object from the network, set this parameter to "" or leave it empty. |
### Observing Data Changes
......@@ -47,7 +47,7 @@ Call **on()** to subscribe to data changes of a distributed data object. When th
| Class| API| Description|
| -------- | -------- | -------- |
| DistributedDataObject| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Subscribes to data changes.|
| DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes. **Callback**: specifies the data changes to unsubscribe from. If this parameter is not specified, all data changes of this distributed data object will be unsubscribed from.|
| DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes. <br/>**Callback**: callback to unregister. If this parameter is not specified, all data changes of this distributed data object will be unsubscribed from. |
### Observing Online or Offline Status
......@@ -59,7 +59,7 @@ Call **on()** to subscribe to status changes of a distributed data object. The s
| DistributedDataObject| on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \| 'offline' }>): void | Subscribes to the status changes of a distributed data object.|
| DistributedDataObject| off(type: 'status', callback?: Callback<{ sessionId: string, deviceId: string, status: 'online' \| 'offline' }>): void | Unsubscribes from status changes of a distributed data object.|
### Saving a Distributed Data Object and Revoking the Data Saving Operation
### Saving or Deleting a Distributed Data Object
Call **save()** to save a distributed data object. When the application is active, the saved data will not be released. When the application exits and restarts, the data saved on the device will be restored.
......@@ -71,11 +71,12 @@ The saved data will be released in the following cases:
- The application has been uninstalled.
- Data is successfully restored.
**Table 6** APIs for saving a distributed data object and revoking the saving operation
**Table 6** APIs for saving and deleting a distributed data object
| Class| API| Description|
| -------- | -------- | -------- |
| DistributedDataObject | save(deviceId: string): Promise&lt;SaveSuccessResponse&gt; | Saves a distributed data object.|
| DistributedDataObject| revokeSave(): Promise&lt;RevokeSaveSuccessResponse&gt; | Revokes the data saving operation.|
| DistributedDataObject| revokeSave(): Promise&lt;RevokeSaveSuccessResponse&gt; | Deletes a distributed data object. |
## How to Develop
......@@ -89,12 +90,10 @@ The following example shows how to implement distributed data object synchroniza
2. Apply for the permission.
Add the required permission (FA model) in the **config.json** file.
Add the permissions required (FA model) to the **config.json** file. The sample code is as follows:
The sample code is as follows:
```json
{
```json
{
"module": {
"reqPermissions": [
{
......@@ -103,30 +102,27 @@ The following example shows how to implement distributed data object synchroniza
]
}
}
```
```
For the apps based on the stage model, see [Declaring Permissions](../security/accesstoken-guidelines.md#stage-model).
This permission must also be granted by the user when the application is started for the first time. The sample code is as follows:
```json
```js
import featureAbility from '@ohos.ability.featureAbility';
function grantPermission() {
console.info('grantPermission');
let context = featureAbility.getContext();
context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
console.info(`result.requestCode=${result.requestCode}`)
})
console.info('end grantPermission');
}
grantPermission();
```
function grantPermission() {
console.info('grantPermission');
let context = featureAbility.getContext();
context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
console.info(`result.requestCode=${result.requestCode}`)
})
console.info('end grantPermission');
}
grantPermission();
```
3. Obtain a distributed data object instance.
The sample code is as follows:
......@@ -142,12 +138,10 @@ The following example shows how to implement distributed data object synchroniza
var sessionId = distributedObject.genSessionId();
```
4. Add the distributed data object instance to the synchronization network.
4. Add the distributed data object instance to a network for data synchronization. The data objects in the synchronization network include the local and remote objects.
The data objects in the synchronization network include the local and remote objects.
The sample code is as follows:
```js
// Local object
var local_object = distributedObject.createDistributedObject({
......@@ -167,16 +161,16 @@ The following example shows how to implement distributed data object synchroniza
parent: undefined,
list: undefined
});
// After learning that the device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
// After learning that the local device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
remote_object.setSessionId(sessionId);
```
5. Observe the data changes of the distributed data object.
You can subscribe to data changes of the remote object. When the data in the remote object changes, a callback will be called to return the data changes.
The sample code is as follows:
```js
function changeCallback(sessionId, changeData) {
console.info("change" + sessionId);
......@@ -185,13 +179,13 @@ The following example shows how to implement distributed data object synchroniza
changeData.forEach(element => {
console.info("changed !" + element + " " + local_object[element]);
});
}
}
}
// To refresh the page in changeCallback, correctly bind (this) to the changeCallback.
local_object.on("change", this.changeCallback.bind(this));
```
6. Modify attributes of the distributed data object.
The object attributes support basic data types (such as number, Boolean, and string) and complex data types (array and nested basic types).
......@@ -250,7 +244,7 @@ The following example shows how to implement distributed data object synchroniza
local_object.on("status", this.statusCallback);
```
10. Save a distributed data object and revoke the data saving operation.
10. Save a distributed data object and delete it.
```js
// Save a distributed data object.
......@@ -261,7 +255,7 @@ The following example shows how to implement distributed data object synchroniza
}, (result) => {
console.info("save local failed.");
});
// Revoke the data saving operation.
// Delete a distributed data object..
g_object.revokeSave().then((result) => {
console.info("revokeSave success.");
}, (result) => {
......@@ -271,7 +265,7 @@ The following example shows how to implement distributed data object synchroniza
11. Unsubscribe from the status changes of the distributed data object.
You can specify the callback to unregister. If you do not specify the callback, this API unregisters all status change callbacks of this distributed data object.
You can specify the callback to unregister. If you do not specify the callback, all status change callbacks of this distributed data object will be unregistered.
The sample code is as follows:
......@@ -282,9 +276,7 @@ The following example shows how to implement distributed data object synchroniza
local_object.off("status");
```
12. Remove a distributed data object from the synchronization network.
Data changes on the local object will not be synchronized to the removed distributed data object.
12. Remove a distributed data object from the synchronization network. Data changes on the local object will not be synchronized to the removed distributed data object.
The sample code is as follows:
......
......@@ -6,20 +6,20 @@ Components support dynamic rotation, translation, and scaling effects. These eff
>
> The initial APIs of this component are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version.
| Name | Type | Default Value | Description |
| ------------------------- | ------------------------------------------------------------ | ------------------------------------- | ------------------------------------------------------------ |
| transform-origin | string<sup>6+</sup> \| \<percentage> \| \<length> string<sup>6+</sup> \| \<percentage> \| \<length> | center center | Origin position of the transformed element. The unit can be px or a percentage (relative to the animation target component). If only one value is specified, the other one is **50%**. The available values for the first string are **left**, **center**, and **right**. The available values for the second string are **top**, **center**, and **bottom**.<br>Example:<br/>transform-origin: 200px 30%<br/>transform-origin: 100px topt<br/>ransform-origin: center center |
| transform | string | - | Translation, rotation, and scaling attributes.<br/>For details, see **transform**. |
| animation<sup>6+</sup> | string | 0s ease 0s 1 normal none running none | Animation attributes in the format of **duration \| timing-function \| delay \| iteration-count \| direction \| fill-mode \| play-state \| name**. The order of the parameters is not specified, but the **duration** and **delay** parameters are parsed based on where they are placed. |
| animation-name | string | - | @keyframes rule. For details, see **@keyframes**. |
| animation-delay | \<time> | 0 | Delay for playing the animation, in ms or s, for example, **1000 ms** or **1s**. The default unit is ms. |
| animation-duration | \<time> | 0 | Animation duration, in ms or s, for example, **1000 ms** or **1s**. The default unit is ms.<br/>NOTE:<br/>**animation-duration** must be specified. Otherwise, the duration is **0**, which means the animation will not be played. |
| animation-iteration-count | number \| infinite | 1 | Number of times that an animation is played. The animation is played once by default. You can set the value to **infinite** to play the animation infinitely. |
| animation-timing-function | string | ease | Speed curve of an animation, which makes the animation more fluent.Available values are as follows: <br>- **linear**: The animation speed keeps unchanged. <br>- **ease**: The animation starts at a low speed and then accelerates. It slows down before the animation ends. **cubic-bezier(0.25, 0.1, 0.25, 1.0)** <br>- **ease-in**: The animation starts at a low speed. **cubic-bezier(0.42, 0.0, 1.0, 1.0)** <br>- **ease-out**: The animation ends at a low speed. **cubic-bezier(0.0, 0.0, 0.58, 1.0)** <br>- **ease-in-out**: The animation starts and ends at a low speed. **cubic-bezier(0.42, 0.0, 0.58, 1.0)****<br>- **friction**: Damping curve, **cubic-bezier(0.2, 0.0, 0.2, 1.0)****<br>- **extreme-deceleration**: Extreme deceleration curve, **cubic-bezier(0.0, 0.0, 0.0, 1.0) curve****<br>- **sharp**: Sharp curve, **cubic-bezier(0.33, 0.0, 0.67, 1.0)****<br>- **rhythm**: Rhythm curve, **cubic-bezier(0.7, 0.0, 0.2, 1.0)****<br>- **smooth**: Smooth curve, **cubic-bezier(0.4, 0.0, 0.4, 1.0)****<br>- **cubic-bezier**: You can customize an animation speed curve in the **cubic-bezier()** function. The x and y values of each input parameter must be between 0 and 1.<br>- steps: step curve <sup>6+</sup>. Syntax: steps(number[, end\|start]); The number parameter is mandatory. The value must be a positive integer. The second parameter is optional. It indicates that the start point or end point of each interval changes step by step. The value can be end or start. The default value is end. |
| animation-direction<sup>6+</sup> | string | normal | Mode of playing the animation. <br>- **normal**: Plays the animation in forward loop mode. <br>- **reverse**: Plays the animation in reverse loop mode. <br>- **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 backward direction. <br>- **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 backward direction. When the animation is played for an even number of times, the playback is in forward direction. |
| animation-fill-mode | string | none | Start and end styles of the animation <br>- **none**: No style is applied to the target before or after the animation is executed. <br>- **forwards**: The target keeps the state at the end of the animation (defined in the last key frame) after the animation is executed. <br>- **backwards**<sup>6+</sup>: The animation uses the value defined in the first key frame during the **animation-delay**. When **animation-direction** is set to **normal** or **alternate**, the value in the **from** key frame is used. When **animation-direction** is set to **reverse** or **alternate-reverse**, the value in the **to** key frame is used.. <br>- **both**<sup>6+</sup>: The animation follows the **forwards** and **backwards** rules. |
| animation-play-state<sup>6+</sup> | string | running | Current state of the animation. <br>- **paused**: paused <br>- **running**: playing |
| transition<sup>6+</sup> | string | all 0 ease 0 | Transition effect when the component status is switched. The following four attributes can be set through the **transition** attribute.<br>- **transition-property**: name of the CSS property for setting the transition effect. Currently, the width, height, and background color are supported. <br>- **transition-duration**: duration required for completing the transition effect, in seconds. <br>- **transition-timing-function**: time curve of the transition effect. The curve provided by the style animation is supported. <br>- **transition-delay**: delay for starting the transition effect, in seconds. |
| Name | Type | Description |
| ------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| transform-origin | string<sup>6+</sup> \| \<percentage> \| \<length> string<sup>6+</sup> \| \<percentage> \| \<length> | Origin position of the transformed element. The unit can be px or a percentage (relative to the animation target component). If only one value is specified, the other one is **50%**. The available values for the first string are **left**, **center**, and **right**. The available values for the second string are **top**, **center**, and **bottom**.<br>Example:<br/>transform-origin: 200px 30%<br/>transform-origin: 100px topt<br/>ransform-origin: center center<br/>Default value: **center center** |
| transform | string | Translation, rotation, and scaling attributes.<br/>For details, see **transform**. |
| animation<sup>6+</sup> | string | Animation attributes in the format of **duration \| timing-function \| delay \| iteration-count \| direction \| fill-mode \| play-state \| name**. The order of the parameters is not specified, but the **duration** and **delay** parameters are parsed based on where they are placed.<br/>Default value: 0s&nbsp;ease&nbsp;0s&nbsp;1&nbsp;normal&nbsp;none&nbsp;running&nbsp;none |
| animation-name | string | @keyframes rule. For details, see **@keyframes**. |
| animation-delay | \<time> | Delay for playing the animation, in ms or s, for example, **1000 ms** or **1s**. The default unit is ms.<br/>Default value: 0 |
| animation-duration | \<time> | Animation duration, in ms or s, for example, **1000 ms** or **1s**. The default unit is ms.<br/>**NOTE**<br/>**animation-duration** must be specified. Otherwise, the duration is **0**, which means the animation will not be played.<br/>Default value: **0** |
| animation-iteration-count | number \| infinite | Number of times that an animation is played. The animation is played once by default. You can set the value to **infinite** to play the animation infinitely.<br/>Default value: **1** |
| animation-timing-function | string | Speed curve of an animation, which makes the animation more fluent.Available values are as follows: <br>- **linear**: The animation speed keeps unchanged. <br>- **ease**: The animation starts slowly, accelerates, and then slows down towards the end. The cubic-bezier curve (0.25, 0.1, 0.25, 1.0) is used.<br>- **ease-in**: The animation starts at a low speed. The cubic-bezier curve (0.42, 0.0, 1.0, 1.0) is used.<br>- **ease-out**: The animation ends at a low speed. The cubic-bezier curve (0.0, 0.0, 0.58, 1.0) is used.<br>- **ease-in-out**: The animation starts and ends at a low speed. The cubic-bezier curve (0.42, 0.0, 0.58, 1.0) is used.<br>- **friction**: The animation uses the friction cubic-bezier curve (0.2, 0.0, 0.2, 1.0).<br>- **extreme-deceleration**: The animation uses the extreme deceleration cubic-bezier curve (0.0, 0.0, 0.0, 1.0).<br>- **sharp**: The animation uses the sharp cubic-bezier curve (0.33, 0.0, 0.67, 1.0).<br>- **rhythm**: The animation uses the rhythm cubic-bezier curve (0.7, 0.0, 0.2, 1.0).<br>- **smooth**: The animation uses the smooth cubic-bezier curve (0.4, 0.0, 0.4, 1.0).<br>- **cubic-bezier**: You can customize an animation speed curve in the **cubic-bezier()** function. The x and y values of each input parameter must be between 0 and 1.<br>- **steps**: The animation uses the step curve<sup>6+</sup>. The syntax is as follows: steps(number[, end\|start]), where the first parameter **number** is mandatory and must be a positive integer; the second parameter is optional and indicates that the start point or end point (default) of each interval changes step by step.<br/>Default value: **ease** |
| animation-direction<sup>6+</sup> | string | Mode of playing the animation. <br>- **normal**: Plays the animation in forward loop mode. <br>- **reverse**: Plays the animation in reverse loop mode. <br>- **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 backward direction. <br>- **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 backward direction. When the animation is played for an even number of times, the playback is in forward direction.<br/>Default value: **normal** |
| animation-fill-mode | string | Start and end styles of the animation <br>- **none**: No style is applied to the target before or after the animation is executed. <br>- **forwards**: The target keeps the state at the end of the animation (defined in the last key frame) after the animation is executed. <br>- **backwards**<sup>6+</sup>: The animation uses the value defined in the first key frame during the **animation-delay**. When **animation-direction** is set to **normal** or **alternate**, the value in the **from** key frame is used. When **animation-direction** is set to **reverse** or **alternate-reverse**, the value in the **to** key frame is used.. <br>- **both**<sup>6+</sup>: The animation follows the **forwards** and **backwards** rules.<br/>Default value: none |
| animation-play-state<sup>6+</sup> | string | Current state of the animation. <br>- **paused**: paused <br>- **running**: playing<br/>Default value: **running** |
| transition<sup>6+</sup> | string | Transition effect when the component status is switched. The following four attributes can be set through the **transition** attribute.<br>- **transition-property**: name of the CSS property for setting the transition effect. Currently, the width, height, and background color are supported. <br>- **transition-duration**: duration required for completing the transition effect, in seconds. <br>- **transition-timing-function**: time curve of the transition effect. The curve provided by the style animation is supported. <br>- **transition-delay**: delay for starting the transition effect, in seconds.<br/>Default value: **all&nbsp;0&nbsp;ease&nbsp;0** |
**Table 1** transform
......
# stepper<a name="EN-US_TOPIC_0000001173324583"></a>
# stepper
The **<stepper\>** component provides a step navigator. When multiple steps are required to complete a task, you can use the **<stepper\>** component to navigate your users through the whole process.
The **\<stepper>** component provides a step navigator. When multiple steps are required to complete a task, you can use the **\<stepper>** component to navigate your users through the whole process.
## Required Permissions<a name="section11257113618419"></a>
> **NOTE**
>
> This component is supported since API version 5. Updates will be marked with a superscript to indicate their earliest API version.
## Required Permissions
None
## Child Components<a name="section9288143101012"></a>
Only the **<stepper-item\>** component is supported.
>![](../../public_sys-resources/icon-note.gif) **NOTE:**
>Steps in the **<stepper\>** are sorted according to the sequence of its **<stepper-item\>** child components.
## Attributes<a name="section191521418142311"></a>
In addition to the attributes in [Universal Attributes](js-components-common-attributes.md), the following attributes are supported.
<a name="table20633101642315"></a>
<table><thead align="left"><tr id="row663331618238"><th class="cellrowborder" valign="top" width="25.040000000000003%" id="mcps1.1.5.1.1"><p id="a45273e2103004ff3bdd3375013e96a2a"><a name="a45273e2103004ff3bdd3375013e96a2a"></a><a name="a45273e2103004ff3bdd3375013e96a2a"></a>Name</p>
</th>
<th class="cellrowborder" valign="top" width="25.11%" id="mcps1.1.5.1.2"><p id="ad5b10d4a60e44bb4a8bbb3b4416d7b27"><a name="ad5b10d4a60e44bb4a8bbb3b4416d7b27"></a><a name="ad5b10d4a60e44bb4a8bbb3b4416d7b27"></a>Type</p>
</th>
<th class="cellrowborder" valign="top" width="11.18%" id="mcps1.1.5.1.3"><p id="ab2ae3d9f60d6475ab95ba095851a9d07"><a name="ab2ae3d9f60d6475ab95ba095851a9d07"></a><a name="ab2ae3d9f60d6475ab95ba095851a9d07"></a>Default Value</p>
</th>
<th class="cellrowborder" valign="top" width="38.67%" id="mcps1.1.5.1.4"><p id="af5c3b773ed0a42e589819a6c8d257ca1"><a name="af5c3b773ed0a42e589819a6c8d257ca1"></a><a name="af5c3b773ed0a42e589819a6c8d257ca1"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row9173122818343"><td class="cellrowborder" valign="top" width="25.040000000000003%" headers="mcps1.1.5.1.1 "><p id="p1517410284349"><a name="p1517410284349"></a><a name="p1517410284349"></a>index</p>
</td>
<td class="cellrowborder" valign="top" width="25.11%" headers="mcps1.1.5.1.2 "><p id="p1174172823415"><a name="p1174172823415"></a><a name="p1174172823415"></a>number</p>
</td>
<td class="cellrowborder" valign="top" width="11.18%" headers="mcps1.1.5.1.3 "><p id="p19174112863417"><a name="p19174112863417"></a><a name="p19174112863417"></a>-</p>
</td>
<td class="cellrowborder" valign="top" width="38.67%" headers="mcps1.1.5.1.4 "><p id="p7174328203414"><a name="p7174328203414"></a><a name="p7174328203414"></a>Index of the <strong id="b1432325813342"><a name="b1432325813342"></a><a name="b1432325813342"></a>&lt;stepper-item&gt;</strong> child component that is currently displayed.</p>
</td>
</tr>
</tbody>
</table>
## Styles<a name="section72591594253"></a>
Styles in [Universal Styles](js-components-common-styles.md) are supported.
>![](../../public_sys-resources/icon-note.gif) **NOTE:**
>By default, the **<stepper\>** component fills entire space of its container. To optimize user experience, it is recommended that the container should be as large as the application window in size, or should be the root component.
## Events<a name="section69611614182911"></a>
In addition to the events in [Universal Events](js-components-common-events.md), the following events are supported.
<a name="table836435619510"></a>
<table><thead align="left"><tr id="row153658563517"><th class="cellrowborder" valign="top" width="10.481048104810482%" id="mcps1.1.4.1.1"><p id="a0ff86a4560fa46bfbeb711d109869422"><a name="a0ff86a4560fa46bfbeb711d109869422"></a><a name="a0ff86a4560fa46bfbeb711d109869422"></a>Name</p>
</th>
<th class="cellrowborder" valign="top" width="41.91419141914191%" id="mcps1.1.4.1.2"><p id="a4c85eb8ca18b4169a25c4a9263fa63ed"><a name="a4c85eb8ca18b4169a25c4a9263fa63ed"></a><a name="a4c85eb8ca18b4169a25c4a9263fa63ed"></a>Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="47.6047604760476%" id="mcps1.1.4.1.3"><p id="ab30b2353efa245fbad4d2aaa2ee33def"><a name="ab30b2353efa245fbad4d2aaa2ee33def"></a><a name="ab30b2353efa245fbad4d2aaa2ee33def"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row990553521718"><td class="cellrowborder" valign="top" width="10.481048104810482%" headers="mcps1.1.4.1.1 "><p id="p1390619353170"><a name="p1390619353170"></a><a name="p1390619353170"></a>finish</p>
</td>
<td class="cellrowborder" valign="top" width="41.91419141914191%" headers="mcps1.1.4.1.2 "><p id="p7906113541716"><a name="p7906113541716"></a><a name="p7906113541716"></a>None</p>
</td>
<td class="cellrowborder" valign="top" width="47.6047604760476%" headers="mcps1.1.4.1.3 "><p id="p7906113531711"><a name="p7906113531711"></a><a name="p7906113531711"></a>Triggered when the last step on the navigator is complete.</p>
</td>
</tr>
<tr id="row24211338161718"><td class="cellrowborder" valign="top" width="10.481048104810482%" headers="mcps1.1.4.1.1 "><p id="p2421113881715"><a name="p2421113881715"></a><a name="p2421113881715"></a>skip</p>
</td>
<td class="cellrowborder" valign="top" width="41.91419141914191%" headers="mcps1.1.4.1.2 "><p id="p16421133841719"><a name="p16421133841719"></a><a name="p16421133841719"></a>None</p>
</td>
<td class="cellrowborder" valign="top" width="47.6047604760476%" headers="mcps1.1.4.1.3 "><p id="p1342113381171"><a name="p1342113381171"></a><a name="p1342113381171"></a>Triggered when users click the skip button, which works only if you have called <strong id="b494641310465"><a name="b494641310465"></a><a name="b494641310465"></a>setNextButtonStatus</strong> method to allow users to skip all steps.</p>
</td>
</tr>
<tr id="row153591438186"><td class="cellrowborder" valign="top" width="10.481048104810482%" headers="mcps1.1.4.1.1 "><p id="p163591032182"><a name="p163591032182"></a><a name="p163591032182"></a>change</p>
</td>
<td class="cellrowborder" valign="top" width="41.91419141914191%" headers="mcps1.1.4.1.2 "><p id="p1535910381819"><a name="p1535910381819"></a><a name="p1535910381819"></a>{ prevIndex: prevIndex, index: index}</p>
</td>
<td class="cellrowborder" valign="top" width="47.6047604760476%" headers="mcps1.1.4.1.3 "><p id="p113602034189"><a name="p113602034189"></a><a name="p113602034189"></a>Triggered when users click the left or right (text) button of the step navigator to switch between steps. <strong id="b108361233105012"><a name="b108361233105012"></a><a name="b108361233105012"></a>prevIndex</strong> indicates the index of the previous step, and <strong id="b1014617216510"><a name="b1014617216510"></a><a name="b1014617216510"></a>index</strong> indicates that of the current step.</p>
</td>
</tr>
<tr id="row6686131145112"><td class="cellrowborder" valign="top" width="10.481048104810482%" headers="mcps1.1.4.1.1 "><p id="p126879113514"><a name="p126879113514"></a><a name="p126879113514"></a>next</p>
</td>
<td class="cellrowborder" valign="top" width="41.91419141914191%" headers="mcps1.1.4.1.2 "><p id="p06871911115113"><a name="p06871911115113"></a><a name="p06871911115113"></a>{ index: index, pendingIndex: pendingIndex }</p>
</td>
<td class="cellrowborder" valign="top" width="47.6047604760476%" headers="mcps1.1.4.1.3 "><p id="p18140235202411"><a name="p18140235202411"></a><a name="p18140235202411"></a>Triggered when users click the next (text) button. <strong id="b155446175519"><a name="b155446175519"></a><a name="b155446175519"></a>index</strong> indicates the index of the current step, and <strong id="b16471726587"><a name="b16471726587"></a><a name="b16471726587"></a>pendingIndex</strong> indicates that of the step to go. The return value is in <strong id="b20759101845911"><a name="b20759101845911"></a><a name="b20759101845911"></a>{pendingIndex:</strong><em id="i13961625125919"><a name="i13961625125919"></a><a name="i13961625125919"></a> pendingIndex</em><strong id="b1882982055918"><a name="b1882982055918"></a><a name="b1882982055918"></a>}</strong> format. You can use <strong id="b79512405598"><a name="b79512405598"></a><a name="b79512405598"></a>pendingIndex</strong> to specify a <strong id="b1235062917016"><a name="b1235062917016"></a><a name="b1235062917016"></a>&lt;stepper-item&gt;</strong> child component as the next step to go.</p>
</td>
</tr>
<tr id="row914118186514"><td class="cellrowborder" valign="top" width="10.481048104810482%" headers="mcps1.1.4.1.1 "><p id="p1414151817510"><a name="p1414151817510"></a><a name="p1414151817510"></a>back</p>
</td>
<td class="cellrowborder" valign="top" width="41.91419141914191%" headers="mcps1.1.4.1.2 "><p id="p16910122113429"><a name="p16910122113429"></a><a name="p16910122113429"></a>{ index: index, pendingIndex: pendingIndex }</p>
</td>
<td class="cellrowborder" valign="top" width="47.6047604760476%" headers="mcps1.1.4.1.3 "><p id="p714261895119"><a name="p714261895119"></a><a name="p714261895119"></a>Triggered when users click the previous (text) button. <strong id="b1620921210312"><a name="b1620921210312"></a><a name="b1620921210312"></a>index</strong> indicates the index of the current step, and <strong id="b1621511211318"><a name="b1621511211318"></a><a name="b1621511211318"></a>pendingIndex</strong> indicates that of the step to go. The return value is in Object:{ <strong id="b102171121532"><a name="b102171121532"></a><a name="b102171121532"></a>{pendingIndex:</strong><em id="i42187121636"><a name="i42187121636"></a><a name="i42187121636"></a> pendingIndex</em><strong id="b1622051211313"><a name="b1622051211313"></a><a name="b1622051211313"></a>}</strong> format. You can use <strong id="b822118128316"><a name="b822118128316"></a><a name="b822118128316"></a>pendingIndex</strong> to specify a <strong id="b192236121235"><a name="b192236121235"></a><a name="b192236121235"></a>&lt;stepper-item&gt;</strong> child component as the previous step.</p>
</td>
</tr>
</tbody>
</table>
## Methods<a name="section1954212182148"></a>
In addition to the methods in [Universal Methods](js-components-common-methods.md), the following events are supported.
<a name="table12793153991411"></a>
<table><thead align="left"><tr id="row15793239141412"><th class="cellrowborder" valign="top" width="19.561956195619562%" id="mcps1.1.4.1.1"><p id="p9794143915141"><a name="p9794143915141"></a><a name="p9794143915141"></a>Name</p>
</th>
<th class="cellrowborder" valign="top" width="24.102410241024103%" id="mcps1.1.4.1.2"><p id="p107942395147"><a name="p107942395147"></a><a name="p107942395147"></a>Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="56.33563356335634%" id="mcps1.1.4.1.3"><p id="p11794133913143"><a name="p11794133913143"></a><a name="p11794133913143"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row157940399145"><td class="cellrowborder" valign="top" width="19.561956195619562%" headers="mcps1.1.4.1.1 "><p id="p1479453913144"><a name="p1479453913144"></a><a name="p1479453913144"></a>setNextButtonStatus</p>
</td>
<td class="cellrowborder" valign="top" width="24.102410241024103%" headers="mcps1.1.4.1.2 "><p id="p10794163914147"><a name="p10794163914147"></a><a name="p10794163914147"></a>{ status: string, label: label }</p>
</td>
<td class="cellrowborder" valign="top" width="56.33563356335634%" headers="mcps1.1.4.1.3 "><p id="p12794143917141"><a name="p12794143917141"></a><a name="p12794143917141"></a>Sets the status of the next (text) button in this step navigator. Available <strong id="b29094326514"><a name="b29094326514"></a><a name="b29094326514"></a>status</strong> values are as follows:</p>
<a name="ol12242138121713"></a><a name="ol12242138121713"></a><ol id="ol12242138121713"><li><strong id="b1032161115214"><a name="b1032161115214"></a><a name="b1032161115214"></a>normal</strong>: The next button is displayed normally and can navigate users to the next step when it is clicked.</li><li><strong id="b1661325920517"><a name="b1661325920517"></a><a name="b1661325920517"></a>disabled</strong>: The next button is grayed out and unavailable.</li><li><strong id="b873175710711"><a name="b873175710711"></a><a name="b873175710711"></a>waiting</strong>: The next button is not displayed, and a process bar is displayed instead.</li><li><strong id="b1990819331594"><a name="b1990819331594"></a><a name="b1990819331594"></a>skip</strong>: The skip button is displayed to allow users to skip all remaining steps.</li></ol>
</td>
</tr>
</tbody>
</table>
## Example<a name="section15374183712313"></a>
```
## Child Components
Only the **\<stepper-item>** component is supported.
> **NOTE**
>
> Steps in the **\<stepper>** are sorted according to the sequence of its **\<stepper-item>** child components.
## Attributes
In addition to the [universal attributes](../arkui-js/js-components-common-attributes.md), the following attributes are supported.
| Name | Type | Default Value | Description |
| ----- | ------ | ---- | ------------------------------ |
| index | number | - | Index of the **<stepper-item>** child component that is currently displayed.|
## Styles
The [universal styles](../arkui-js/js-components-common-styles.md) are supported.
> **NOTE**
>
> By default, the **\<stepper>** component fills entire space of its container. To optimize user experience, it is recommended that the container should be as large as the application window in size, or should be the root component.
## Events
In addition to the [universal events](../arkui-js/js-components-common-events.md), the following events are supported.
| Name | Parameter | Description |
| ------ | ---------------------------------------- | ---------------------------------------- |
| finish | - | Triggered when the last step on the navigator is complete. |
| skip | - | Triggered when users click the skip button, which works only if you have called **setNextButtonStatus** method to allow users to skip all steps.|
| change | { prevIndex: prevIndex, index: index} | Triggered when users click the left or right (text) button of the step navigator to switch between steps. **prevIndex** indicates the index of the previous step, and **index** indicates that of the current step.|
| next | { index: index, pendingIndex: pendingIndex } | Triggered when users click the next (text) button. **index** indicates the index of the current step, and **pendingIndex** indicates that of the step to go. The return value is in **{pendingIndex:*** pendingIndex***}** format. You can use **pendingIndex** to specify a **<stepper-item>** child component as the next step to go.|
| back | { index: index, pendingIndex: pendingIndex } | Triggered when users click the previous (text) button. **index** indicates the index of the current step, and **pendingIndex** indicates that of the step to go. The return value is in Object:{ **{pendingIndex:*** pendingIndex***}** format. You can use **pendingIndex** to specify a **<stepper-item>** child component as the previous step.|
## Methods
In addition to the [universal methods](../arkui-js/js-components-common-methods.md), the following methods are supported.
| Name | Parameter | Description |
| ------------------- | ---------------------------------------- | ---------------------------------------- |
| setNextButtonStatus | { status: string, label: label } | Sets the status of the next (text) button in this step navigator. Available **status** values are as follows:<br>- **normal**: The next button is displayed normally and can navigate users to the next step when it is clicked.<br>- **disabled**: The next button is grayed out and unavailable.<br>- **waiting**: The next button is not displayed, and a process bar is displayed instead.<br>- **skip**: The skip button is displayed to allow users to skip all remaining steps.|
## Example
```html
<!-- xxx.hml -->
<div class = "container">
<stepper class="stepper" id="mystepper" index="0" onnext="nextclick" onback="backclick">
......@@ -150,7 +89,7 @@ In addition to the methods in [Universal Methods](js-components-common-methods.
</div>
```
```
```css
/* xxx.css */
.container {
margin-top: 20px;
......@@ -174,7 +113,7 @@ In addition to the methods in [Universal Methods](js-components-common-methods.
}
```
```
```js
// xxx.js
export default {
data: {
......@@ -215,5 +154,4 @@ export default {
}
```
![](figures/en-us_image_0000001127125114.gif)
![en-us_image_0000001127125114](figures/en-us_image_0000001127125114.gif)
......@@ -12,7 +12,6 @@
- [Resource File Categories](ui-ts-basic-resource-file-categories.md)
- [Accessing Resources](ts-resource-access.md)
- [Pixel Units](ts-pixel-units.md)
- [Types](ts-types.md)
- Declarative Syntax
- [Overview](ts-syntax-intro.md)
- General UI Description Specifications
......@@ -20,8 +19,8 @@
- Declarative UI Description Specifications
- [Configuration Without Parameters](ts-parameterless-configuration.md)
- [Configuration with Mandatory Parameters](ts-configuration-with-mandatory-parameters.md)
- [Attribute Configuration](ts-attribution-configuration.md)
- [Attribute Configuration](ts-attribution-configuration.md)
- [Event Configuration](ts-event-configuration.md)
- [Child Component Configuration](ts-child-component-configuration.md)
- Componentization
......@@ -73,7 +72,8 @@
- [Building a Food Category List Layout](ui-ts-building-category-list-layout.md)
- [Building a Food Category Grid Layout](ui-ts-building-category-grid-layout.md)
- [Implementing Page Redirection and Data Transmission](ui-ts-page-redirection-data-transmission.md)
- [Recommendations for Improving Performance](ts-performance-improvement-recommendation.md)
- JavaScript-based Web-like Development Paradigm
- [Overview](ui-js-overview.md)
- Framework
......
# Recommendations for Improving Performance
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
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.
```ts
@Entry
@Component
struct MyComponent {
@State arr: number[] = Array.from(Array(100), (v,k) =>k); // Construct an array of 0 to 99.
build() {
List() {
ForEach(this.arr, (item: number) => {
ListItem() {
Text(`item value: ${item}`)
}
}, (item: number) => item.toString())
}
}
}
```
The preceding code snippet loads all of the 100 list elements at a time during page loading. This is generally not desirable. Instead, what we need is to load data from the data source and create corresponding components on demand. This can be achieved through lazy loading. The sample code is as follows:
```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: string[] = ['item value: 0', 'item value: 1', 'item value: 2']
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() {
List() {
LazyForEach(this.data, (item: string) => {
ListItem() {
Row() {
Text(item).fontSize(20).margin({ left: 10 })
}
}
.onClick(() => {
this.data.pushData('item value: ' + this.data.totalCount())
})
}, item => item)
}
}
}
```
The preceding code initializes only three list elements during page loading and loads a new list item each time a list element is clicked.
## 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.
```ts
@Entry
@Component
struct MyComponent {
@State isVisible: Visibility = Visibility.Visible;
build() {
Column() {
Button ("Show/Hide")
.onClick(() => {
if (this.isVisible == Visibility.Visible) {
this.isVisible = Visibility.None
} else {
this.isVisible = Visibility.Visible
}
})
Row().visibility(this.isVisible)
.width(300).height(300).backgroundColor(Color.Pink)
}.width('100%')
}
}
```
To avoid the preceding issue, use the **if** conditional statement instead. The sample code is as follows:
```ts
@Entry
@Component
struct MyComponent {
@State isVisible: boolean = true;
build() {
Column() {
Button ("Show/Hide")
.onClick(() => {
this.isVisible = !this.isVisible
})
if (this.isVisible) {
Row()
.width(300).height(300).backgroundColor(Color.Pink)
}
}.width('100%')
}
}
```
## Prioritizing Flex over Column/Row
By default, the flex container needs to re-lay out flex items to comply with the **flexShrink** and **flexGrow** settings. This may result in drop in rendering performance.
```ts
@Entry
@Component
struct MyComponent {
build() {
Flex({ direction: FlexDirection.Column }) {
Flex().width(300).height(200).backgroundColor(Color.Pink)
Flex().width(300).height(200).backgroundColor(Color.Yellow)
Flex().width(300).height(200).backgroundColor(Color.Grey)
}
}
}
```
To avoid the preceding issue, replace **Flex** with **Column** and **Row**, which can create the same page layout as **Flex** does.
```ts
@Entry
@Component
struct MyComponent {
build() {
Column() {
Row().width(300).height(200).backgroundColor(Color.Pink)
Row().width(300).height(200).backgroundColor(Color.Yellow)
Row().width(300).height(200).backgroundColor(Color.Grey)
}
}
}
```
## 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.
```ts
@Entry
@Component
struct MyComponent {
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
build() {
Scroll() {
List() {
ForEach(this.arr, (item) => {
ListItem() {
Text(`item value: ${item}`).fontSize(30).margin({ left: 10 })
}.height(100)
}, (item) => item.toString())
}
}.backgroundColor(Color.Pink)
}
}
```
Therefore, in the above scenario, you are advised to set the width and height for the **\<List>** component as follows:
```ts
@Entry
@Component
struct MyComponent {
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
build() {
Scroll() {
List() {
ForEach(this.arr, (item) => {
ListItem() {
Text(`item value: ${item}`).fontSize(30).margin({ left: 10 })
}.height(100)
}, (item) => item.toString())
}.width('100%').height(500)
}.backgroundColor(Color.Pink)
}
}
```
## Minimizing White Blocks During Swiping
To minimize white blocks durign swiping, expand the UI loading range by increasing the value of **cachedCount** for the **\<List>** and **\<Grid>** components. **cachedCount** indicates the number of list or grid items preloaded outside of the screen.
If an item needs to request an online image, set **cachedCount** as appropriate so that the the image is downloaded in advance before the item comes into view on the screen, thereby reducing the number of white blocks.
The following is an example of using **cachedCount**:
```ts
@Entry
@Component
struct MyComponent {
private source: MyDataSource = new MyDataSource();
build() {
List() {
LazyForEach (this.source, item => {
ListItem() {
Text("Hello" + item)
.fontSize(100)
.onAppear(()=>{
console.log("appear:" + item)
})
}
})
}.cachedCount(3) // Increase the value to enlarge the range of logs that appear.
}
}
class MyDataSource implements IDataSource {
data: number[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
public totalCount(): number {
return this.data.length
}
public getData(index: number): any {
return this.data[index]
}
registerDataChangeListener(listener: DataChangeListener): void {
}
unregisterDataChangeListener(listener: DataChangeListener): void {
}
}
```
**Instructions**
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 newline at end of file
# Types
## Resource
The **Resource** type is used to reference resources for setting component attribute values.
If a **Resource** object is created using `$r` or `$rawfile`, modifying attribute values of the object is prohibited.
- `$r('belonging.type.name')`
**belonging**: system or application resource. The value can be **'sys'** or **'app'**.
**type**: resource type, which can be **'color'**, **'float'**, **'string'**, or **'media'**.
**name**: resource name, which is determined during resource definition.
- `$rawfile('filename')`
**filename**: name of the file in **resources/rawfile** of the project.
| Name | Type | Readable| Writable| Description |
| ----------------------- | ------ | ---- | ---- | ---------- |
| id | number | Yes | No | Resource ID. |
| type | number | Yes | No | Resource type. |
| params | any[] | Yes | No | Optional resource parameters. |
| bundleName<sup>9+</sup> | string | Yes | No | Bundle name. |
| moduleName<sup>9+</sup> | string | Yes | No | Module name.|
## Length
The **Length** type is used to represent a size unit.
| Type | Description |
| -------- | ------------------------------------------------------------ |
| string | String type. Explicitly specify the length unit, for example, **'10px'**, or the length in percentage, for example, **'100%'**.|
| number | Number type. The default unit is vp. |
| Resource | Size referenced from system or application resources. |
## ResourceStr<sup>8+</sup>
The **ResourceStr** type is used to represent the types that can be used by input parameters of the string type.
| Type | Description |
| -------- | --------------------------------------------------- |
| string | String type. |
| Resource | String referenced from system or application resources.|
## Padding
The **Padding** type is used to describe the padding areas in different directions of a component.
| Name | Type | Mandatory| Description |
| ------- | ------ | ---- |------------------------ |
| top | Length | No | Height of the padding area on the top of the component. |
| right | Length | No | Width of the padding area on the right of the component.|
| bottom | Length | No | Height of the padding area at the bottom of the component. |
| left | Length | No | Width of the padding area on the left of the component.|
## Margin
The **Margin** type is used to describe the margin areas in different directions of a component.
| Name | Type | Mandatory| Description |
| ------- | ------ | ---- |------------------------ |
| top | Length | No | Height of the margin area above the component. |
| right | Length | No | Width of the margin area on the right of the component.|
| bottom | Length | No | Height of the margin area below the component. |
| left | Length | No | Width of the margin area on the left of the component.|
## EdgeWidths<sup>9+</sup>
The **EdgeWidths** type is used to describe the edge widths in different directions of a component.
| Name | Type | Mandatory| Description |
| ------- | ------ | ---- |--------------------- |
| top | Length | No | Width of the top edge of the component. |
| right | Length | No | Width of the right edge of the component. |
| bottom | Length | No | Width of the bottom edge of the component. |
| left | Length | No | Width of the left edge of the component. |
## BorderRadiuses<sup>9+</sup>
The **BorderRadiuses** type is used to describe the radius of the rounded corners of a component.
| Name | Type | Mandatory| Description |
| ----------- | ------ | ---- |--------------------- |
| topLeft | Length | No | Radius of the top left rounded corner of the component. |
| topRight | Length | No | Radius of the top right rounded corner of the component. |
| bottomLeft | Length | No | Radius of the bottom left rounded corner of the component. |
| bottomRight | Length | No | Radius of the bottom right rounded corner of the component. |
## EdgeColors<sup>9+</sup>
The **EdgeColors** type is used to describe the edge colors of a component.
| Name | Type | Mandatory| Description |
| ------- | --------------- | ---- |--------------------- |
| top | ResourceColor | No | Color of the top edge of the component. |
| right | ResourceColor | No | Color of the right edge of the component. |
| bottom | ResourceColor | No | Color of the bottom edge of the component. |
| left | ResourceColor | No | Color of the left edge of the component. |
## EdgeStyles<sup>9+</sup>
The **EdgeStyles** type is used to describe the edge styles of a component.
| Name | Type | Mandatory| Description |
| ------- | ------------- | ---- |--------------------- |
| top | BorderStyle | No | Style of the top edge of the component. |
| right | BorderStyle | No | Style of the right edge of the component. |
| bottom | BorderStyle | No | Style of the bottom edge of the component. |
| left | BorderStyle | No | Style of the left edge of the component. |
## Offset
The **Offset** type is used to describe the offset coordinates of a component in the layout.
| Name | Type | Mandatory| Description |
| -------- | ------ | ---- |--------------------- |
| dx | Length | Yes | Horizontal offset. |
| dy | Length | Yes | Vertical offset. |
## ResourceColor<sup>8+</sup>
The **ResourceColor** type is used to describe the color types of resources.
| Type | Description |
| -------- | ----------------------- |
| [Color](../reference/arkui-ts/ts-appendix-enums.md#color) | Color enum. |
| number | Color in the hexadecimal notation. |
| string | Color in the RGB or RGBA notion. |
| Resource | Color referenced from system or application resources.|
## LengthConstrain
The **LengthConstrain** type is used to limit the maximum and minimum lengths of a component.
| Name | Type | Mandatory| Description |
| --------- | ------ | ---- |---------------- |
| minLength | Length | Yes | Minimum length of the component. |
| maxLength | Length | Yes | Maximum length of the component. |
## Font
The **Font** type is used to set the text style.
| Name | Type | Mandatory| Description |
| ------ | ------------------------------ | ---- | ------------------------------------------------------------ |
| size | number | No | Font size. If the value is of the number type, the unit fp is used. |
| weight | number | No | Font weight. For the number type, the value ranges from 100 to 900, at an interval of 100. The default value is **400**. A larger value indicates a larger font weight.|
| family | [FontWeight](../reference/arkui-ts/ts-appendix-enums.md#fontweight) \| number \| string | No | Font family of the text. Use commas (,) to separate multiple fonts. The priority of the fonts is the sequence in which they are placed. An example value is **'Arial, sans-serif'**.|
| style | string \| Resource | No | Font style. |
## Area<sup>8+</sup>
The **Area** type is used to describe the area information of the target element.
| Name | Type | Description |
| -------------- | -------- | ------------------------------------------------- |
| width | Length | Width of the target element. The value is of the number type when being used as the return value and the unit is vp. |
| height | Length | Height of the target element. The value is of the number type when being used as the return value and the unit is vp. |
| position | Position | Position of the upper left corner of the target element relative to that of the parent element. |
| globalPosition | Position | Position of the upper left corner of the target element relative to that of the page. |
## Position<sup>8+</sup>
The **Position** type is used to represent coordinates of a point.
| Name | Type | Mandatory| Description |
| ----- | ------- | ---- | ------------------------------------------- |
| x | Length | No | X coordinate. The value is of the number type when being used as the return value and the unit is vp. |
| y | Length | No | Y coordinate. The value is of the number type when used as the return value and the unit is vp. |
## ConstraintSizeOptions
The **ConstraintSizeOptions** type is used to set the constraint size of a component, thereby limiting the size range during component layout.
| Name | Type | Mandatory | Description |
| --------- | -------- | ---- | -------------- |
| minWidth | Length | No | Minimum width of the element. |
| maxWidth | Length | No | Maximum width of the element. |
| minHeight | Length | No | Minimum height of the element. |
| maxHeight | Length | No | Maximum height of the element. |
## SizeOptions
The **SizeOptions** type is used to set the width and height.
| Name | Type | Mandatory| Description |
| ------- | -------- | ---- | -------------- |
| width | Length | No | Width of the element. |
| height | Length | No | Height of the element. |
## BorderOptions
The **BorderOptions** type is used to provide border information.
| Name | Type | Mandatory | Description |
| ------ | ----------------------- | ---- | ----------- |
| width | Length \| EdgeWidths<sup>9+</sup> | No | Border width. |
| color | ResourceColor \| EdgeColors<sup>9+</sup> | No | Border color. |
| radius | Length \| BorderRadiuses<sup>9+</sup> | No | Border radius. |
| style | [BorderStyle](../reference/arkui-ts/ts-appendix-enums.md#borderstyle) \| EdgeStyles<sup>9+</sup> | No | Border style. |
## ColorFilter<sup>9+</sup>
The **ColorFilter** type is used to create a color filter with a 4*5 matrix.
| Name | Type | Mandatory | Description |
| ----------- | -------- | ------ | --------------------------------------------------------------- |
| constructor | number[] | Yes | Constructor for creating a color filter with a 4\*5 matrix. The input parameter is [m*n], which is the matrix value in row m and column n. The matrix is row-first. |
## CustomBuilder<sup>8+</sup>
The **CustomBuilder** type is used to define custom UI descriptions in component attribute methods.
| Name | Type | Description |
| ------------- | ---------------------- | ------------------------------------------------------------ |
| CustomBuilder | ()&nbsp;=&gt;&nbsp;any | Builder of component attribute methods for defining custom UI descriptions. This type of method must be decorated by **@Builder**. For details, see [@Builder](ts-component-based-builder.md).|
# &lt;stepper&gt; Development
# \<stepper> Development
When multiple steps are required to complete a task, you can use the **&lt;stepper&gt;** component to navigate your users through the whole process. For details, see [stepper](../reference/arkui-js/js-components-container-stepper.md).
When multiple steps are required to complete a task, you can use the **<stepper>** component to navigate your users through the whole process. For details, see [stepper](../reference/arkui-js/js-components-container-stepper.md).
> **NOTE**
......@@ -9,9 +8,9 @@ When multiple steps are required to complete a task, you can use the **&lt;stepp
> This component is supported since API version 5.
## Creating a &lt;stepper&gt; Component
## Creating a \<stepper> Component
Create a **&lt;stepper&gt;** component in the .hml file under **pages/index**.
Create a **\<stepper>** component in the .hml file under **pages/index**.
```html
<!-- xxx.hml -->
......@@ -85,7 +84,7 @@ text{
![en-us_image_0000001267767837](figures/en-us_image_0000001267767837.gif)
Set the **label** attribute to customize the button text for the **&lt;stepper-item&gt;**.
Set the **label** attribute to customize the label for the **\<stepper-item>**.
```html
<!-- xxx.hml -->
......@@ -149,8 +148,7 @@ export default {
## Setting Styles
By default, the **&lt;stepper&gt;** component fills entire space of its container. The sample code below shows how to set the border and background color using the **border** and **background-color** attributes.
By default, the **\<stepper>** component fills entire space of its container. The sample code below shows how to set the border and background color using the **border** and **background-color** attributes.
```html
<!-- xxx.hml -->
<div class="container" >
......@@ -194,7 +192,7 @@ text{
## Adding Events
The **&lt;stepper&gt;** component supports the **finish**, **change**, **next**, **back**, and **skip** events.
The **\<stepper>** component supports the **finish**, **change**, **next**, **back**, and **skip** events.
- When the **change** and **next** or **back** events exist at the same time, the **next** or **back** event is executed before the **change** event.
......@@ -271,12 +269,14 @@ export default {
stepperChange(e){
console.log("stepperChange"+e.index)
prompt.showToast({
// index indicates the sequence number of the current step.
message: 'Previous step: '+e.prevIndex+"-------Current step:"+e.index
})
},
stepperNext(e){
console.log("stepperNext"+e.index)
prompt.showToast({
// pendingIndex indicates the sequence number of the step to be redirected to.
message: 'Current step:'+e.index+"-------Next step:"+e.pendingIndex
})
var index = {pendingIndex:e.pendingIndex }
......@@ -295,9 +295,9 @@ export default {
## Example Scenario
Select the options displayed on the page. Your selection will be shown in real time. Click the next button to dynamically change the font color and font size on the page.
In this example, you can select the options displayed on the page and see how your selection takes effect in real time. Clicking the next button will dynamically change the font color and font size of the selected option.
Use the &lt;stepper&gt; component to navigate through the steps. Create a [&lt;toggle&gt;](../reference/arkui-js/js-components-basic-toggle.md) component to implement the functions of selection and displaying the selection result. Then use the [&lt;select&gt;](../reference/arkui-js/js-components-basic-select.md) component to dynamically change the font color or size of the selected options.
Use a **\<stepper>** component to navigate through the steps. Create a **\<Toggle>**(../reference/arkui-js/js-components-basic-toggle.md) component to implement the functions of selecting an option and displaying the selection result. Then use the **\<Select>**(../reference/arkui-js/js-components-basic-select.md) component to dynamically change the font color or size of the selected option.
```html
<!-- xxx.hml -->
......@@ -404,4 +404,4 @@ export default {
}
```
![en-us_image_0000001267887817](figures/en-us_image_0000001267887817.gif)
\ No newline at end of file
![en-us_image_0000001267887817](figures/en-us_image_0000001267887817.gif)
......@@ -404,8 +404,8 @@ typedef struct {
} TreeNodeInfo;
typedef struct {
TreeNodeInfo nodeInfo; /* Tree information data structure of each node. */
void *userInfo; /* User information data structure of each node. */
TreeNodeInfo nodeInfo; /* Data structure of each node's tree information. */
void *userInfo; /* Data structure of each node's user information. */
} TreeNode;
```
......
......@@ -12,14 +12,14 @@
### 创建数据对象实例
创建一个分布式数据对象实例,开发者可以通过source指定分布式对象中的属性。
创建一个分布式数据对象实例,开发者可以通过source指定分布式数据对象中的属性。
**表1** 分布式数据对象实例创建接口
| 包名 | 接口名 | 描述 |
| -------- | -------- | -------- |
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | 创建一个分布式数据对象实例,用于数据操作。 <br>-&nbsp;source:设置distributedObject的属性。<br>-&nbsp;DistributedObject:返回值是创建好的分布式对象。 |
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | 创建一个分布式数据对象实例,用于数据操作。 <br>-&nbsp;source:设置分布式数据对象的属性。<br>-&nbsp;DistributedObject:返回值是创建好的分布式数据对象。 |
### 创建分布式数据对象sessionId
......@@ -39,7 +39,7 @@
| 类名 | 接口名 | 描述 |
| -------- | -------- | -------- |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | 为分布式数据对象设置sessionId。<br>&nbsp;sessionId:分布式对象在可信组网中的标识ID。如果要退出分布式组网,设置为""或不设置均可。 |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | 为分布式数据对象设置sessionId。<br>&nbsp;sessionId:分布式数据对象在可信组网中的标识ID。如果要退出分布式组网,设置为""或不设置均可。 |
### 订阅数据变更
......@@ -214,7 +214,7 @@
// 删除所有的变更回调
localObject.off("change");
```
9. 监听分布式对象的上下线。可以监听对端分布式数据对象的上下线。
9. 监听分布式数据对象的上下线。可以监听对端分布式数据对象的上下线。
```js
function statusCallback(sessionId, networkId, status) {
......@@ -242,7 +242,7 @@
console.info("revokeSave failed.");
});
```
11. 删除监听分布式对象的上下线。可以指定删除监听的上下线回调;也可以不指定,这将会删除该分布式数据对象的所有上下线回调。
11. 删除监听分布式数据对象的上下线。可以指定删除监听的上下线回调;也可以不指定,这将会删除该分布式数据对象的所有上下线回调。
```js
// 删除上下线回调statusCallback
......@@ -250,7 +250,7 @@
// 删除所有的上下线回调
localObject.off("status");
```
12. 退出同步组网。分布式对象退出组网后,本地的数据变更对端不会同步。
12. 退出同步组网。分布式数据对象退出组网后,本地的数据变更对端不会同步。
```js
localObject.setSessionId("");
......
......@@ -26,70 +26,30 @@
| -------- | -------- | -------- |
| ohos.sensor | sensor.on(sensorType, callback:AsyncCallback&lt;Response&gt;): void | 持续监听传感器数据变化 |
| ohos.sensor | sensor.once(sensorType, callback:AsyncCallback&lt;Response&gt;): void | 获取一次传感器数据变化 |
| ohos.sensor | sensor.off(sensorType, callback:AsyncCallback&lt;void&gt;): void | 注销传感器数据的监听 |
| ohos.sensor | sensor.off(sensorType, callback?:AsyncCallback&lt;void&gt;): void | 注销传感器数据的监听 |
## 开发步骤
1. 获取设备上传感器的数据,需要在“config.json”里面进行配置请求权限。具体如下:
```
"reqPermissions": [
{
"name": "ohos.permission.ACCELEROMETER",
"reason": "",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.GYROSCOPE",
"reason": "",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.ACTIVITY_MOTION",
"reason": "ACTIVITY_MOTION_TEST",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.READ_HEALTH_DATA",
"reason": "HEALTH_DATA_TEST",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
}
]
```
1. 获取设备上传感器的数据前,需要检查是否已经配置请求相应的权限。 <br>
系统提供的传感器权限有:
- ohos.permission.ACCELEROMETER
- ohos.permission.GYROSCOPE
- ohos.permission.ACTIVITY_MOTION
- ohos.permission.READ_HEALTH_DATA
具体配置方式请参考[权限申请声明](../security/accesstoken-guidelines.md)
2. 持续监听传感器数据变化。
```
import sensor from "@ohos.sensor"
sensor.on(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data){
console.info("Subscription succeeded. data = " + data);// 调用成功,打印对应传感器的数据
}
);
import sensor from "@ohos.sensor";
sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data){
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,持续监听传感器接口的结果如下图所示:
......@@ -99,11 +59,8 @@
3. 注销传感器数据监听。
```
import sensor from "@ohos.sensor"
sensor.off(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function() {
console.info("Succeeded in unsubscribing from acceleration sensor data.");// 注销成功,返回打印结果
}
);
import sensor from "@ohos.sensor";
sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER);
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,注销传感器成功结果如下图所示:
......@@ -113,11 +70,10 @@
4. 获取一次传感器数据变化。
```
import sensor from "@ohos.sensor"
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
console.info("Data obtained successfully. data=" + data);// 获取数据成功,打印对应传感器的数据
}
);
import sensor from "@ohos.sensor";
sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,获取数据成功日志如下图所示:
......@@ -127,12 +83,13 @@
若接口调用不成功,建议使用try/catch语句捕获代码中可能出现的错误信息。例如:
```
import sensor from "@ohos.sensor";
try {
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
console.info("Data obtained successfully. data=" + data);// 获取数据成功,打印对应传感器的数据
sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
} catch (error) {
console.error(error);
console.error("Get sensor data fail");
}
```
## 相关实例
......
......@@ -22,42 +22,7 @@
## 开发步骤
1. 控制设备上的振动器,需要在`config.json`里面进行配置请求权限。具体如下:
```
"reqPermissions": [
{
"name": "ohos.permission.ACCELEROMETER",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.VIBRATE",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.ACTIVITY_MOTION",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
}
]
```
1. 控制设备上的振动器,需要申请权限ohos.permission.VIBRATE。具体配置方式请参考[权限申请声明](../security/accesstoken-guidelines.md)
2. 触发设备振动。
......
......@@ -23,7 +23,7 @@ Vibrator属于控制类小器件,主要包含以下四个模块:Vibrator API
## 约束与限制
在使用振动器时,开发者需要配置请求振动器的权限ohos.permission.VIBRATE,才能控制振动器振动,权限类型是system_grant
在使用振动器时,开发者需要配置请求振动器的权限ohos.permission.VIBRATE,才能控制振动器振动。
......@@ -18,7 +18,7 @@ extraData代表发送请求的额外数据,支持如下数据:
适用于:OpenHarmony SDK 3.2.2.5版本,API9 Stage模型
错误码28代表CURLE_OPERATION_TIMEDOUT 。网络请求底层使用libcurl库,更多错误码可以查看相应文档。
错误码28代表CURLE_OPERATION_TIMEDOUT,操作超时。网络请求底层使用libcurl库,更多错误码可以查看相应文档。
参考文档:[开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-http.md#response%E5%B8%B8%E7%94%A8%E9%94%99%E8%AF%AF%E7%A0%81)[Curl错误码](https://curl.se/libcurl/c/libcurl-errors.html)
......
# 一次开发,多端部署
- [前言](about-this-document.md)
- [简介](introduction.md)
- 应用UX设计
- [设计原则和要点](design-principles.md)
- 应用架构设计
- [应用导航结构设计要求](navigation-design.md)
- [应用页面结构设计](page-design.md)
- 界面布局
- [概述](layout-design-intro.md)
- 布局基础
- [栅格系统](layout-grid.md)
- [自适应布局](layout-adaptive.md)
- [响应式布局](layout-responsive.md)
- [布局基础运用案例](layout-design-cases.md)
- 人机交互
- [交互基础](interaction-basics.md)
- [常见输入方式](common-input-modes.md)
- [交互事件归一](design-interaction-events-unification.md)
- 视觉风格
- [视觉基础](visual-style-basics.md)
- [色彩](visual-style-color.md)
- [字体](visual-style-font.md)
- [图标](visual-style-icon.md)
- [多态控件](design-polymorphic-components.md)
- [设计自检表](design-checklist.md)
- [资源](resource.md)
- [IDE使用](ide-usage.md)
- 一多能力的页面开发介绍
- 布局能力
- [布局能力简介](layout-intro.md)
- 自适应布局
- [自适应布局简介](adaptive-layout-intro.md)
- [拉伸能力](adaptive-layout-stretching.md)
- [均分能力](adaptive-layout-equalization.md)
- [占比能力](adaptive-layout-proportion.md)
- [缩放能力](adaptive-layout-scaling.md)
- [延伸能力](adaptive-layout-extension.md)
- [隐藏能力](adaptive-layout-hiding.md)
- [折行能力](adaptive-layout-wrapping.md)
- 响应式布局
- [栅格断点系统](grid-breakpoint.md)
- [媒体查询](media-query.md)
- [典型场景](responsive-layout-cases.md)
- [交互归一](interaction-events-unification.md)
- [多态组件](polymorphic-components.md)
- [资源使用](resource-usage.md)
- [一多能力的功能开发介绍](development-intro.md)
- 案例应用
- 短信应用
- [概览](sms-intro.md)
- 会话详情页面
- [页面结构](sms-session-page-structure.md)
- [顶部标题栏](sms-session-page-title-bar.md)
- [底部输入栏](sms-session-page-input-field.md)
- [信息列表](sms-session-page-message-list.md)
- [组合成型](sms-session-page-combined.md)
- [总结](sms-session-summary.md)
- [桌面应用](cases-home-screen.md)
- [常见问题](faqs.md)
# 一次开发,多端部署
- [前言](foreword.md)
- [简介](introduction.md)
- [从一个例子开始](start-with-a-example.md)
- 应用UX设计
- [设计原则和要点](design-principles.md)
- 应用架构设计
- [应用导航结构设计要求](navigation-design.md)
- [应用页面结构设计](page-design.md)
- 界面布局
- [概述](interface-layout-design-intro.md)
- 布局基础
- [栅格系统](design-grid.md)
- [自适应布局](design-adaptive-layout.md)
- [响应式布局](design-responsive-layout.md)
- [布局基础运用案例](design-layout-cases.md)
- 人机交互
- [交互基础](interaction-basics.md)
- [常见输入方式](common-input-modes.md)
- [交互事件归一](design-interaction-event-normalization.md)
- 视觉风格
- [视觉基础](visual-basics.md)
- [色彩](visual-style-color.md)
- [字体](visual-style-font.md)
- [图标](visual-style-icon.md)
- [多态控件](design-polymorphic-controls.md)
- [设计自检表](design-checklist.md)
- [设计交付](design-delivery.md)
- [资源](design-resources.md)
- [工程管理](ide-using.md)
- 页面开发的一多能力介绍
- [简介](page-development-intro.md)
- 布局能力
- [布局简介](layout-intro.md)
- [自适应布局](adaptive-layout.md)
- [响应式布局](responsive-layout.md)
- [典型布局场景](typical-layout-scenario.md)
- 典型页面场景
- [应用市场首页](appgallery-home-page.md)
- [音乐专辑页](music-album-page.md)
- [交互归一](interaction-event-normalization.md)
- [多态组件](polymorphic-controls.md)
- [资源使用](resource-usage.md)
- [功能开发的一多能力介绍](development-intro.md)
- [案例应用](case.md)
- [常见问题](faq.md)
# 前言
本指导的目的是快速及全面地指导读者使用OpenHarmony提供的“一次开发,多端部署”(本指导中简称“一多”)能力开发多设备应用。在应用开发前,开发者应尽可能全面考虑应用支持多设备的情况,避免在后期加入新的类型设备时需要对应用架构进行大幅调整。
## 本指导面向的读者
本指导适合开发OpenHarmony应用的UX设计师、应用开发人员,本指导书统称为“应用开发者”。这两者是根据开发角色不同而进行的区分。对于个人或者规模较小的应用,两者可能是同一个个体,但应当从角色上加以区分。
## 如何阅读本指导
应用在需求明确后,开发过程大致分为:应用设计(包含界面UX设计、业务功能设计)- 工程设计和创建 - 功能代码实现。本指导也是基于这个流程进行的内容编排。
阅读本文档时,应尽量按照章节顺序进行阅读。如果区分开发角色,那么UX设计师可以仅阅读第3章,而开发人员可以从第4章开始阅读。但无论何种角色,我们强烈建议阅读第2章。
本文档各章节简介如下:
- 第1章[前言](about-this-document.md)说明本指导面向的读者、如何阅读本指导等,指引读者更好地阅读。
- 第2章[简介](introduction.md)简短介绍了“一多”的背景、定义、目标、以及用于指导后续开发的一些基础知识。
- 第3章[应用UX设计](design-principles.md)介绍了应用UX设计理念。主要阐述了应用设计之初UX设计的原则和要点。该章节主要面向应用的UX设计师。
UX设计原则应该考虑多设备的“差异性” 、“一致性”、“灵活性”、“兼容性”。
UX设计要点则从6个方面阐述如何进行多设备应用设计,分别是“自适应应用架构”、“响应式界面布局”、“交互归一”、“视觉参数化”、“多态控件”、“针对性优化”。
最后,给出设计自检表,用于检查应用UX设计是否合理。
- 第4章[IDE使用](ide-usage.md)介绍了从工程角度如何开始开发应用,这非常有用,让读者可以直接上手创建多设备应用的工程,是后面学习“一多”能力的上手基础。
- 第5章[一多能力的页面开发介绍](layout-intro.md)、第6章[一多能力的功能开发介绍](development-intro.md)介绍了OpenHarmony提供的“一多”能力,其中每个能力都提供了代码示例和UX效果,让读者可以快速学习“一多”能力。
- 第7章提供了两个案例应用,阐述了从应用设计到开发这一过程中如何实践前面章节介绍的设计思路或“一多”能力,让读者可以整体上掌握“一多”在应用开发过程中的知识。
- 第8章[常见问题](faqs.md)提供了常见问题(FAQ),方便读者查阅。
本指导在介绍过程中还包括一些“说明”。这些“说明”,表示例外情况或者额外信息的补充。
# 均分能力
均分能力是指容器组件尺寸发生变化时,增加或减小的空间均匀分配给容器组件内所有空白区域。它常用于内容数量固定、均分显示的场景,比如工具栏、底部菜单栏等。
均分能力通常通过使用 **Flex均分布局**[Flex组件](../../reference/arkui-ts/ts-container-flex.md)的justifyContent属性设置为FlexAlign.SpaceEvenly)实现,即子元素在Flex主轴方向等间距布局,相邻元素之间的间距、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 均分能力是特殊场景下拉伸能力的简单实现。也可以借助其它方式实现均分能力,如在每个组件间添加Blank组件等。
## 示例:
父容器尺寸变化过程中,图标及文字的尺寸不变,图标间的间距及图标离左右边缘的距离同时均等改变。
![zh-cn_image_0000001291935425](figures/zh-cn_image_0000001291935425.gif)
```ts
@Entry
@Component
struct EquipartitionCapabilitySample {
const list: number [] = [0, 1, 2, 3];
@State rate: number = 0.6;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 30, max: 60, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Column() {
// 均匀分配父容器主轴方向的剩余空间
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
ForEach(this.list, (item) => {
Column() {
Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}.width(80).height(102)
})
}
// 均匀分配父容器主轴方向的剩余空间
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
ForEach(this.list, (item) => {
Column() {
Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}.width(80).height(102)
})
}
}
.width(this.rate * 100 + '%')
.height(222)
.padding({ top: 16 })
.backgroundColor('#FFFFFF')
.borderRadius(16)
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
# 延伸能力
延伸能力是指容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。它可以根据显示区域的尺寸,显示不同数量的元素。
延伸能力通常有两种实现方式:
- 通过[List组件](../../reference/arkui-ts/ts-container-list.md)实现。
- 通过[Scroll组件](../../reference/arkui-ts/ts-container-scroll.md)配合[Row组件](../../reference/arkui-ts/ts-container-row.md)[Column组件](../../reference/arkui-ts/ts-container-column.md)实现。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> List、Row或Column组件中子节点的在页面显示时就已经全部完成了布局计算及渲染,只不过受限于父容器尺寸,用户只能看到一部分。随着父容器尺寸增大,用户可以看到的子节点数目也相应的增加。用户还可以通过手指滑动触发列表滑动,查看被隐藏的子节点。
## 示例:
当父容器的尺寸发生改变时,页面中显示的图标数量随之发生改变。
分别通过List组件实现及通过Scroll组件配合Row组件实现。
![zh-cn_image_0000001245295918](figures/zh-cn_image_0000001245295918.gif)
(1)通过List组件实现。
```ts
@Entry
@Component
struct ExtensionCapabilitySample1 {
@State rate: number = 0.60;
const appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7];
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 8, max: 60, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Row({ space: 10 }) {
// 通过List组件实现隐藏能力
List({ space: 10 }) {
ForEach(this.appList, (item) => {
ListItem() {
Column() {
Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}.width(80).height(102)
}.width(80).height(102)
})
}
.padding({ top: 16, left: 10 })
.listDirection(Axis.Horizontal)
.width('100%')
.height(118)
.borderRadius(16)
.backgroundColor(Color.White)
}
.width(this.rate * 100 + '%')
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
(2)通过Scroll组件配合Row组件实现。
```ts
@Entry
@Component
struct ExtensionCapabilitySample2 {
private scroller: Scroller = new Scroller()
@State rate: number = 0.60;
@State appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7];
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 8, max: 60, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
// 通过Scroll和Row组件实现隐藏能力
Scroll(this.scroller) {
Row({ space: 10 }) {
ForEach(this.appList, () => {
Column() {
Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}.width(80).height(102)
})
}
.padding({ top: 16, left: 10 })
.height(118)
.borderRadius(16)
.backgroundColor(Color.White)
}
.scrollable(ScrollDirection.Horizontal)
.width(this.rate * 100 + '%')
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
# 隐藏能力
隐藏能力是指容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏,其中相同显示优先级的子组件同时显示或隐藏。它是一种比较高级的布局方式,常用于分辨率变化较大,且不同分辨率下显示内容有所差异的场景。主要思想是通过增加或减少显示内容,来保持最佳的显示效果。
隐藏能力通过设置**布局优先级**(displayPriority属性)来控制显隐,当布局主轴方向剩余尺寸不足以满足全部元素时,按照布局优先级大小,从小到大依次隐藏,直到容器能够完整显示剩余元素。具有相同布局优先级的元素将同时显示或者隐藏。
可以访问[布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md),了解displayPriority属性的详细信息。
## 示例:
父容器尺寸发生变化时,其子元素按照预设的优先级显示或隐藏。
![zh-cn_image_0000001245136646](figures/zh-cn_image_0000001245136646.gif)
```ts
@Entry
@Component
struct HiddenCapabilitySample {
@State rate: number = 0.45;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 10, max: 45, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ direction: FlexDirection.Column,
justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center }) {
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Image($r("app.media.favorite"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 12 })
.displayPriority(1) // 布局优先级
Image($r("app.media.down"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 12 })
.displayPriority(2) // 布局优先级
Image($r("app.media.pause"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 12 })
.displayPriority(3) // 布局优先级
Image($r("app.media.next"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 12 })
.displayPriority(2) // 布局优先级
Image($r("app.media.list"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 12 })
.displayPriority(1) // 布局优先级
}
.width(this.rate * 100 + '%')
.height(96)
.borderRadius(16)
.backgroundColor('#FFFFFF')
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
# 自适应布局简介
多设备间最大的差异是屏幕分辨率,差异分辨率适配离不开自适应布局的能力。针对常见的开发场景,方舟开发框架提炼了七种自适应布局能力。这些布局可以独立使用,也可多种布局叠加使用。
| 自适应布局类别 | 自适应布局能力 | 使用场景 |
| -------- | -------- | -------- |
| 自适应拉伸 | [拉伸能力](adaptive-layout-stretching.md) | 容器组件尺寸发生变化时,增加或减小的空间**全部分配**给容器组件内**指定区域**。 |
| [均分能力](adaptive-layout-equalization.md) | 容器组件尺寸发生变化时,增加或减小的空间**均匀分配**给容器组件内**所有空白区域**。 ||
| 自适应缩放 | [占比能力](adaptive-layout-proportion.md) | 子组件的宽高**按照预设的比例**,随容器组件发生变化。 |
| [缩放能力](adaptive-layout-scaling.md) | 子组件的宽高**按照预设的比例**,随容器组件发生变化,且变化过程中子组件的**宽高比不变**。 ||
| 自适应延伸 | [延伸能力](adaptive-layout-extension.md) | 容器组件内的子组件,按照其**在列表中的先后顺序**,随容器组件尺寸变化显示或隐藏。 |
| [隐藏能力](adaptive-layout-hiding.md) | 容器组件内的子组件,按照其**预设的显示优先级**,随容器组件尺寸变化显示或隐藏。**相同显示优先级的子组件同时显示或隐藏**。 ||
| 自适应折行 | [折行能力](adaptive-layout-wrapping.md) | 容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,**自动换行**。 |
下面我们依次介绍这几种自适应布局能力。
# 占比能力
占比能力是指子组件的宽高按照预设的比例,随父容器组件发生变化。
占比能力通常有两种实现方式:
- 将子组件的宽高设置为父组件宽高的百分比,详见[尺寸设置](../../reference/arkui-ts/ts-universal-attributes-size.md)[长度类型](../../ui/ts-types.md#长度类型)
- 通过layoutWeight属性配置互为兄弟关系的组件在父容器主轴方向的布局权重,详见[尺寸设置](../../reference/arkui-ts/ts-universal-attributes-size.md)
- 当父容器尺寸确定时,其子组件按照开发者配置的权重比例分配父容器中主轴方向的空间。
- 仅当父容器是Row、Colomn或者Flex时,layoutWeight属性才会生效。
- 设置layoutWeight属性后,组件本身的尺寸会失效。比如同时设置了.width('40%')和.layoutWeight(1),那么只有.layoutWeight(1)会生效。
layoutWeight存在使用限制,所以实际使用过程中大多通过将子组件宽高设置为父组件的百分比来实现占比能力。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 占比能力在实际开发中使用的非常广泛,可以通过很多不同的方式实现占比能力,如还可以通过[Grid组件](../../reference/arkui-ts/ts-container-grid.md)的columnsTemplate属性设置网格容器中列的数量及其宽度比例,或通过配置子组件在栅格(本章后文将详细介绍栅格系统)中占据不同的列数来实现占比能力。本小节仅介绍最基础和常用的实现方式,局限性较大或比非常小众的实现方式,本文不再展开介绍。
## 示例:
简单的播放控制栏,其中“上一首”、“播放/暂停”、“下一首”的layoutWeight属性都设置为1,因此它们按照“1:1:1”的比例均分父容器主轴方向的空间。
将三个按钮的.layoutWeight(1)分别替换为.width('33%')、.width('34%')、.width('33%'),也可以实现与当前同样的显示效果。
![zh-cn_image_0000001292374353](figures/zh-cn_image_0000001292374353.gif)
```ts
@Entry
@Component
struct ProportionCapabilitySample {
@State rate: number = 0.5;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: 100, min: 25, max: 50, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Column() {
Row() {
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Image($r("app.media.down"))
.width(48)
.height(48)
}
.height(96)
.layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Image($r("app.media.pause"))
.width(48)
.height(48)
}
.height(96)
.layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重
.backgroundColor('#66F1CCB8')
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Image($r("app.media.next"))
.width(48)
.height(48)
}
.height(96)
.layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重
}
.width(this.rate * 100 + '%')
.height(96)
.borderRadius(16)
.backgroundColor('#FFFFFF')
}
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
# 缩放能力
缩放能力是指子组件的宽高按照预设的比例,随容器组件发生变化,且变化过程中子组件的宽高比不变。
缩放能力通过使用百分比布局配合**固定宽高比**(aspectRatio属性)实现当容器尺寸发生变化时,内容自适应调整。
可以访问[布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md),了解aspectRatio属性的详细信息。
## 示例:
为方便查看效果,示例中特意给Column组件加了边框。可以看到Column组件随着其Flex父组件尺寸变化而缩放的过程中,始终保持预设的宽高比,其中的图片也始终正常显示。
![zh-cn_image_0000001245614634](figures/zh-cn_image_0000001245614634.gif)
```ts
@Entry
@Component
struct ScaleCapabilitySample {
@State width: number = 400;
@State height: number = 400;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.width, min: 100, max: 400, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.width = value;
})
.position({ x: '20%', y: '80%' })
Slider({ value: this.height, min: 100, max: 400, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.height(50)
.onChange((value: number) => {
this.height = value;
})
.position({ x: '20%', y: '87%' })
}
build() {
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Column() {
Image($r("app.media.illustrator")).width('100%').height('100%')
}
.aspectRatio(1) // 固定宽高比
.border({ width: 2, color: "#66F1CCB8"}) // 边框,仅用于展示效果
}
.backgroundColor("#FFFFFF")
.height(this.width)
.width(this.height)
this.slider()
}.width('100%')
.height('100%')
.backgroundColor("#F1F3F5")
}
}
```
# 拉伸能力
拉伸能力是指容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。
拉伸能力通常通过Flex布局的flexGrow和flexShrink属性实现,详见[Flex布局](../../reference/arkui-ts/ts-universal-attributes-flex-layout.md)
- flexGrow:仅当父容器宽度大于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例拉伸,分配父容器的多余空间。
- flexShrink:仅当父容器宽度小于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例收缩,分配父容器的不足空间。
特别的,当开发者期望将父容器的剩余空间全部分配给某空白区域时,也可以通过Blank组件实现。注意仅当父组件为Row\Column\Flex组件时,Blank组件才会生效,详见[Blank组件](../../reference/arkui-ts/ts-basic-components-blank.md)
## 示例1:
本示例中的页面由中间的内容区(包含一张图片)以及两侧的留白区组成。
中间内容区的宽度设置为400vp,同时将flexGrow属性设置为1,flexShrink属性设置为0。
两侧留白区的宽度设置为150vp,同时将flexGrow属性设置为0,flexShrink属性设置为1。
因此父容器的基准尺寸是700vp(150vp+400vp+150vp)。
当父容器的尺寸大于700vp时,父容器中多余的空间全部分配给中间内容区。
当父容器的尺寸小于700vp时,左右两侧的留白区按照“1:1”的比例收缩(即平均分配父容器的不足空间)。
![zh-cn_image_0000001245613530](figures/zh-cn_image_0000001245613530.gif)
```ts
@Entry
@Component
struct FlexibleCapabilitySample1 {
@State width: number = 402;
// 底部滑块,可以通过拖拽滑块改变容器尺寸。
@Builder slider() {
Slider({ value: this.width, min: 402, max: 1000, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.width = value;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center }) {
Column() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center }) {
// 通过flexGrow和flexShink属性,将多余的空间全部分配给图片,将不足的控件全部分配给两侧空白区域。
Row().width(150).height(400).backgroundColor('#FFFFFF')
.flexGrow(0).flexShrink(1)
Image($r("app.media.illustrator")).width(400).height(400)
.objectFit(ImageFit.Contain)
.backgroundColor("#66F1CCB8")
.flexGrow(1).flexShrink(0)
Row().width(150).height(400).backgroundColor('#FFFFFF')
.flexGrow(0).flexShrink(1)
}.width(this.width)
}
this.slider()
}.width('100%').height('100%').backgroundColor('#F1F3F5')
}
}
```
## 示例2:
文字和开关的尺寸固定,仅有中间空白区域(Blank组件)随父容器尺寸变化而伸缩。
![zh-cn_image_0000001266042114](figures/zh-cn_image_0000001266042114.gif)
```ts
@Entry
@Component
struct FlexibleCapabilitySample2 {
@State rate: number = 0.8;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 30, max: 80, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center }) {
Column() {
Row() {
Text('飞行模式')
.fontSize(16)
.width(135)
.height(22)
.fontWeight(FontWeight.Medium)
.lineHeight(22)
Blank() // 通过Blank组件实现拉伸能力
Toggle({ type: ToggleType.Switch })
.width(36)
.height(20)
}
.height(55)
.borderRadius(12)
.padding({ left: 13, right: 13 })
.backgroundColor('#FFFFFF')
.width(this.rate * 100 + '%')
}
this.slider()
}.width('100%').height('100%').backgroundColor('#F1F3F5')
}
}
```
# 折行能力
折行能力是指容器组件尺寸发生变化,当布局方向尺寸不足以显示完整内容时自动换行。它常用于横竖屏适配或默认设备向平板切换的场景。
折行能力通过使用 **Flex折行布局** (将warp属性设置为FlexWrap.Wrap)实现,当横向布局尺寸不足以完整显示内容元素时,通过折行的方式,将元素显示在下方。
可以访问[Flex组件](../../reference/arkui-ts/ts-container-flex.md),了解Flex组件的详细用法。
## 示例:
父容器中的图片尺寸固定,当父容器尺寸发生变化,其中的内容做自适应换行。
![zh-cn_image_0000001292215677](figures/zh-cn_image_0000001292215677.gif)
```ts
@Entry
@Component
struct WrapCapabilitySample {
@State rate: number = 0.7;
const imageList: Resource [] = [
$r('app.media.flexWrap1'),
$r('app.media.flexWrap2'),
$r('app.media.flexWrap3'),
$r('app.media.flexWrap4'),
$r('app.media.flexWrap5'),
$r('app.media.flexWrap6')
];
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 50, max: 70, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '87%' })
}
build() {
Flex({ justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) {
Column() {
// 通过Flex组件warp参数实现自适应折行
Flex({
direction: FlexDirection.Row,
alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Center,
wrap: FlexWrap.Wrap
}) {
ForEach(this.imageList, (item) => {
Image(item).width(183).height(138).padding(10)
})
}
.backgroundColor('#FFFFFF')
.padding(20)
.width(this.rate * 100 + '%')
.borderRadius(16)
}
.width('100%')
this.slider()
}.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
```
# 应用市场首页
本小节将以应用市场首页为例,介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。本示例已经在[OpenHarmony应用示例](https://gitee.com/openharmony/applications_app_samples/tree/master/MultiDeviceAppDev/AppMarket)中开源,读者可以根据需要自行下载源码并运行及查看效果。
## 页面设计
一个典型的应用市场首页的UX设计如下所示。
| sm | md | lg |
| -------- | -------- | -------- |
| ![zh-cn_image_0000001328579522](figures/zh-cn_image_0000001328579522.png) | ![zh-cn_image_0000001328259918](figures/zh-cn_image_0000001328259918.png) | ![zh-cn_image_0000001379179861](figures/zh-cn_image_0000001379179861.png) |
观察应用市场首页的页面设计,不同断点下的页面设计有较多相似的地方。
据此,我们可以将页面分拆为多个组成部分。
1. 底部/侧边导航栏
2. 标题栏与搜索栏
3. 运营横幅
4. 快捷入口
5. 精品应用
| sm | md | lg |
| -------- | -------- | -------- |
| ![zh-cn_image_0000001379299533](figures/zh-cn_image_0000001379299533.png) | ![zh-cn_image_0000001328259922](figures/zh-cn_image_0000001328259922.png) | ![zh-cn_image_0000001379179865](figures/zh-cn_image_0000001379179865.png) |
接下来我们逐一分析各部分的实现。
## 底部/侧边导航栏
在sm和md断点下,导航栏在底部;在lg断点下,导航栏在左侧。可以通过[Tab组件](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-container-tabs.md)的barPosition和vertical属性控制TabBar的位置,同时还可以通过barWidth和barHeight属性控制TabBar的尺寸。
```
@Entry
@Component
struct Index {
...
build() {
// 设置TabBar在主轴方向起始或结尾位置
Tabs({ barPosition: this.currentBreakpoint === "lg" ? BarPosition.Start : BarPosition.End }) {
// 首页
TabContent() {
Home()
}.tabBar(this.tabItem1)
TabContent() {}.tabBar(this.tabItem2)
TabContent() {}.tabBar(this.tabItem3)
TabContent() {}.tabBar(this.tabItem4)
TabContent() {}.tabBar(this.tabItem5)
}
.backgroundColor('#F1F3F5')
.barMode(BarMode.Fixed)
.barWidth(this.currentBreakpoint === "lg" ? 96 : '100%')
.barHeight(this.currentBreakpoint === "lg" ? '60%' : 56)
// 设置TabBar放置在水平或垂直方向
.vertical(this.currentBreakpoint === "lg")
}
}
```
另外在sm及lg断点下,TabBar中各个Item的图标和文字是按照垂直方向排布的,在md断点下,TabBar中各个Item的图标和文字是按照水平方向排布的。
```
@Component
export default struct TabBarItem {
...
build() {
if (this.currentBreakpoint !== 'md' ) {
// sm及lg断点下,tabBarItem中的图标和文字垂直排布
Column() {
...
}.justifyContent(FlexAlign.Center).height('100%').width('100%')
} else {
// md断点下,tabBarItem中的图标和文字水平排布
Row() {
....
}.justifyContent(FlexAlign.Center).height('100%').width('100%')
}
}
}
```
## 标题栏与搜索栏
标题栏和搜索栏,在sm和md断点下分两行显示,在lg断点下单行显示,可以通过栅格实现。在sm和md断点下,标题栏和搜索栏占满12列,此时会自动换行显示。在lg断点下,标题栏占8列而搜索栏占4列,此时标题栏和搜索栏在同一行中显示。
| | sm/md | lg |
| -------- | -------- | -------- |
| 效果图 | ![zh-cn_image_0000001379385785](figures/zh-cn_image_0000001379385785.png) | ![zh-cn_image_0000001379464977](figures/zh-cn_image_0000001379464977.jpg) |
| 栅格布局图 | ![zh-cn_image_0000001379464981](figures/zh-cn_image_0000001379464981.png) | ![zh-cn_image_0000001328745102](figures/zh-cn_image_0000001328745102.png) |
```
@Component
export default struct IndexHeader {
...
build() {
// 借助栅格实现标题栏和搜索栏在不同断点下的不同布局效果。
GridRow() {
GridCol({ span: { xs: 12, lg: 8 } }) {
this.titleBar()
}
GridCol({ span: { xs: 12, lg: 4 } }) {
this.searchBar()
}
}
.width('100%')
}
}
```
## 运营横幅
不同断点下的运营横幅,sm断点下显示一张图片,md断点下显示两张图片,lg断点下显示三张图片。可以通过[Swiper组件的displayCount属性](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-container-swiper.md)实现目标效果。
```
@Component
export default struct IndexSwiper {
...
@Builder swiperItem(imageSrc) {
Image(imageSrc)
.width('100%')
.aspectRatio(2.5)
.objectFit(ImageFit.Fill)
}
build() {
Swiper() {
this.swiperItem($r('app.media.ic_public_swiper1'))
this.swiperItem($r('app.media.ic_public_swiper2'))
this.swiperItem($r('app.media.ic_public_swiper3'))
...
}
.autoPlay(true)
.indicator(false)
.itemSpace(10)
// 配置不同断点下运行横幅中展示的图片数量
.displayCount(this.currentBreakpoint === 'sm' ? 1 : (this.currentBreakpoint === 'md' ? 2 : 3))
.width('100%')
.padding({ left: 12, right: 12, bottom: 16, top: 16 })
}
}
```
## 快捷入口
在不同的断点下,快捷入口的5个图标始终均匀排布,这是典型的均分能力使用场景。
```
@Component
@Component
export default struct IndexEntrance {
build() {
// 将justifyContent参数配置为FlexAlign.SpaceEvenly实现均分布局
Row() {
ForEach(entranceIcons, (icon: AllIcons) => {
// 各快捷入口的图标及名称
Column() { ... }
})
}
.width('100%')
.height(64)
.justifyContent(FlexAlign.SpaceEvenly)
.padding({ left: 12, right: 12 })
}
}
```
## 精品应用
随着可用显示区域的增加,精品应用中显示的图标数量也不断增加,这是典型的延伸能力使用场景。精品游戏的实现与精品应用类似,不再展开分析。
```
@Component
@Component
export default struct IndexApps {
...
build() {
Column() {
this.appListHeader()
// 借助List组件能力,实现延伸能力场景
List({ space: this.currentBreakpoint === 'lg' ? 44 : 20}) {
LazyForEach(new MyAppSource(this.apps), app => {
ListItem() {
// 每个应用的图标、名称及安装按钮
this.appListItem(app)
}
}, app => app.id)
}
.width('100%')
.height(this.currentBreakpoint === 'lg' ? 140 : 120)
.listDirection(Axis.Horizontal)
}
.width('100%')
.height(this.currentBreakpoint === 'lg' ? 188 : 164)
.padding({ bottom: 8, left: 12, right: 12 })
}
}
```
## 运行效果
将上述各页面主要部分组合在一起后,即可完成整体页面开发。
```
@Component
struct IndexContent {
...
build() {
List() {
// 运营横幅
ListItem() {
IndexSwiper()
}
// 快捷入口
ListItem() {
IndexEntrance()
}
// 精品应用
ListItem() {
IndexApps({ title: $r('app.string.boutique_application'), apps: appList })
}
// 精品游戏
ListItem() {
IndexApps({ title: $r('app.string.boutique_game'), apps: gameList })
}
}
.width("100%")
}
}
@Component
export default struct Home {
...
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
// 标题栏和搜索栏
IndexHeader()
// 运营横幅、快捷入口、精品应用、精品游戏等
IndexContent()
}
.height('100%')
.backgroundColor("#F1F3F5")
}
}
```
本页面的实际运行效果如下图所示。
| sm | md | lg |
| -------- | -------- | -------- |
| ![zh-cn_image_0000001334345550](figures/zh-cn_image_0000001334345550.jpg) | ![zh-cn_image_0000001385105477](figures/zh-cn_image_0000001385105477.jpg) | ![zh-cn_image_0000001384985569](figures/zh-cn_image_0000001384985569.jpg) |
<!--no_check-->
\ No newline at end of file
# 应用架构设计
- **[应用导航结构设计要求](navigation-design.md)**
- **[应用页面结构设计](page-design.md)**
\ No newline at end of file
......@@ -5,7 +5,7 @@
**基于触控的交互**
很多设备都拥有支持多点触控的屏幕,允许用户使用手指和/或手写笔进行交互。它们与屏幕的接触状态、数量以及运动行为被识别成触控手势和操作,可以支持多种交互功能和体验(例如点击、滑动、缩放、旋转)。在多数情况下,应将触控交互作为用户首要的交互方式。
很多设备的屏幕都支持多点触控,允许用户通过手指或手写笔进行交互。它们与屏幕的接触状态、数量以及运动行为被识别成触控手势和操作,可以支持多种交互功能和体验(例如点击、滑动、缩放、旋转)。在多数情况下,应将触控交互作为用户首要的交互方式。
以下是基础的手势操作:
......
# 设计自检表
设计自检表详细列举出了在全场景设备设计和开发过程中应当注意的设计规则,这将帮助应用减少用户舆情且提升用户体验的一致性。
自检表的要求范围分为“必选”与“推荐”两类。必选类一般为已总结出的较优解决方案或效果,表示相关设计需要按照此原则统一执行;推荐类指可能受应用品牌风格或业务特殊性影响,可适量做出修改。
请参考以下表格范围内提出的要求对应用进行检查。
| **类型** | **条目** | **说明** |
| -------- | ------------------ | ------------------------------------------------------------ |
| 应用架构 | 导航结构 | 保证同一应用/服务在各设备上导航结构一致。 |
| | 界面框架 | 尽量使用推荐的常用界面架构,以更好达到一多效果。 |
| 布局 | 自适应布局 | 关注布局标注是否逻辑合理,是否具备自适应能力。保证在不同尺寸和分辨率的设备上能够无错位/不截断/不变形地正常显示。 |
| | 响应式布局 | 关注布局是否更有效利用屏幕控件,是否具备响应式能力。保证在不同尺寸和分辨率的设备上不过多空白(50%以上)/不过于拥挤(间距小于16vp,明显截断)。 |
| | 页面结构 | 尽量使用推荐的常用页面结构,以更好达到一多效果。 |
| | 页面结构优化 | 在通用能力不适用业务诉求时,进行页面特殊优化,保证在具体设备上的使用体验。 |
| 人机交互 | 输入方式 | 需保证在各设备上完整支持触摸、鼠标、触控、键盘、遥控器、摇杆等交互方式,并符合标准定义。 |
| | 交互归一 | 应使用系统提供的控件以达到一致的交互体验。如有定制,需保证在各场景下,不同输入设备上的操作与指南要求一致。需特别注意鼠标行为。 |
| 视觉风格 | 单位 | 用于界面布局的单位应全部使用vp。只针对严格控制元素尺寸的场景使用px。 |
| | 色彩 | 用于色彩的赋值应使用分层参数。推荐支持深色模式,需保证界面在系统切换色彩模式时没有识别性问题。 |
| | 字体 | 尽量使用fp为文字大小单位,需要响应系统大字体模式,确保系统调节字体大小后,界面字体能响应变化大小,并且界面布局没有出现布局错乱问题。 |
# 设计自检表
设计自检表详细列举出了在全场景设备设计和开发过程中应当注意的设计规则,这将帮助应用减少用户舆情且提升用户体验的一致性。
自检表的要求范围分为“必选”与“推荐”两类。必选类一般为已总结出的较优解决方案或效果,表示相关设计需要按照此原则统一执行;推荐类指可能受应用品牌风格或业务特殊性影响,可适量做出修改。
请参考以下表格范围内提出的要求对应用进行检查。
| **类型** | **条目** | **说明** |
| -------- | ------------------ | ------------------------------------------------------------ |
| 应用架构 | 导航结构 | 在各设备上页面导航结构保持一致(同时出多个设备的UX设计)。 |
| 布局 | 拉通设计 | 拉通各设备的布局设计,保证在不同尺寸和分辨率的设备上能够无错位/不截断/不变形/不过多空白(50%以上)/不过于拥挤(间距小于16vp,明显截断)/无大图大字体地正常显示。 |
| | 响应式设计 | 栅格布局只能占N列以及N列内部的Gutter,不包含N列两侧的Gutter。 |
| | 响应式设计 | 明确标注使用什么类型的栅格、给出在不同断点下栅格三要素取值。 |
| | 响应式设计 | 按容器去对齐栅格,而不是内部子元素对齐栅格。 |
| | 响应式设计 | 栅格除了页面布局设计外,在做局部栅格设计时,需要通过明显方式如颜色等进行标注区分,避免混淆。 |
| | 响应式设计 | 禁止出现标注了栅格但实际没有通过栅格进行布局设计,避免混淆。 |
| | 自适应设计 | 非栅格设计场景下,明确标注自适应布局能力。自适应布局能力有:拉伸、均分、占比、缩放、延伸、隐藏、折行。 |
| 人机交互 | 输入方式 | 需保证在各设备上完整支持触摸、鼠标、触控、键盘、遥控器、摇杆等交互方式,并符合标准定义。 |
| | 交互归一 | 应使用系统提供的控件以达到一致的交互体验。如有定制,需保证在各场景下,不同输入设备上的操作与指南要求一致。需特别注意鼠标行为。 |
| 视觉风格 | 单位 | 用于界面布局的单位应全部使用vp。只针对严格控制元素尺寸的场景使用px。 |
| | 色彩 | 用于色彩的赋值应使用分层参数。推荐支持深色模式,需保证界面在系统切换色彩模式时没有识别性问题。 |
| | 字体 | 使用fp为文字大小单位,需要响应系统大字体模式,确保系统调节字体大小后,界面字体能响应变化大小,并且界面布局没有出现布局错乱问题。 |
| 多态控件 | 支持常用的控件状态 | 确保控件不同状态下的视觉效果没有缺失。控件的常用状态有:正常态、不可用态、点击态、获焦态、激活态、悬停态。 |
\ No newline at end of file
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册