提交 d16fb7dd 编写于 作者: D donglin 提交者: Gitee

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

Signed-off-by: Ndonglin <donglin9@huawei.com>
# Creating a Custom Component
In ArkUI, components are what's displayed on the UI. They can be classified as built-in components – those directly provided by ArkUI framework, and custom components – those defined by developers. Defining the entire application UI with just built-in components would lead to a monolithic design, low code maintainability, and poor execution performance. A good UI is the result of a well-thought-out development process, with such factors as code reusability, separation of service logic from the UI, and version evolution carefully considered. Creating custom components that encapsulate the UI and some business logic is a critical step in this process.
In ArkUI, components are what's displayed on the UI. They can be classified as built-in components – those directly provided by the ArkUI framework, and custom components – those defined by developers. Defining the entire application UI with just built-in components would lead to a monolithic design, low code maintainability, and poor execution performance. A good UI is the result of a well-thought-out development process, with such factors as code reusability, separation of service logic from the UI, and version evolution carefully considered. Creating custom components that encapsulate the UI and some business logic is a critical step in this process.
The custom component has the following features:
......
......@@ -29,7 +29,9 @@ liba
│ └── module.json5
└── oh-package.json5
```
Below is an example of the **index.ets** file content:
In the entry file **index.ets**, declare the APIs to be exposed.
Below is an example:
```ts
// liba/src/main/ets/index.ets
......@@ -168,7 +170,7 @@ struct Index {
}
```
## Inter-Application HSP Distribution
## Inter-Application HSP Distribution (for System Applications Only)
Inter-application HSPs are not completely integrated into an application. They are distributed by being preset in the system version or installed with an application on the device. To be specific:
1. Some frequently-used inter-application HSPs are preset in the system version.
2. When a user downloads an application from the application market, if the application market detects that the application depends on one or more inter-application HSPs and any of these HSPs are not installed on the target device, it will download the application as well as the missing HSPs for the user. In this way, the application can use the features shared through the HSPs properly.
......
......@@ -5,13 +5,11 @@ For details about the definition of a system common event, see [Support in @ohos
**System capability**: SystemCapability.Notification.CommonEvent
## COMMON_EVENT_BOOT_COMPLETED
Indicates that the user has finished booting and the system has been loaded.
- Value: **usual.event.BOOT_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVER_STARTUP_COMPLETED
## [COMMON_EVENT_BOOT_COMPLETED](./common_event/commonEvent-ability.md)
Indicates that the user has finished the boot process.
## COMMON_EVENT_LOCKED_BOOT_COMPLETED
(Reserved, not supported yet) Indicates that the user has finished booting and the system has been loaded but the screen is still locked.
(Reserved, not supported yet) Indicates that the user has finished the boot process but the screen is still locked.
- Value: **usual.event.LOCKED_BOOT_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVER_STARTUP_COMPLETED
......@@ -40,31 +38,26 @@ Indicates that the device is connected to an external power supply.
- Value: **usual.event.POWER_CONNECTED**
- Required subscriber permissions: none
## COMMON_EVENT_POWER_DISCONNECTED
Indicates that the device is disconnected from the external power supply.
- Value: **usual.event.POWER_DISCONNECTED**
- Required subscriber permissions: none
## COMMON_EVENT_SCREEN_OFF
Indicates that the device screen is off and the device is in sleep mode.
- Value: **usual.event.SCREEN_OFF**
- Required subscriber permissions: none
## COMMON_EVENT_SCREEN_ON
Indicates that the device screen is on and the device is in interactive state.
- Value: **usual.event.SCREEN_ON**
- Required subscriber permissions: none
## COMMON_EVENT_THERMAL_LEVEL_CHANGED<sup>8+</sup>
Indicates that the device's thermal level has changed.
- Value: **usual.event.THERMAL_LEVEL_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_USER_PRESENT<sup>(deprecated)</sup>
(Reserved, not supported yet) Indicates that the user unlocks the device.
- Value: **usual.event.USER_PRESENT**
......@@ -78,43 +71,36 @@ Indicates that the system time has changed as time ticks by.
- Value: **usual.event.TIME_TICK**
- Required subscriber permissions: none
## COMMON_EVENT_TIME_CHANGED
Indicates that the system time is set.
- Value: **usual.event.TIME_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_DATE_CHANGED
(Reserved, not supported yet) Indicates that the system date has changed.
- Value: **usual.event.DATE_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_TIMEZONE_CHANGED
Indicates that the system time zone has changed.
- Value: **usual.event.TIMEZONE_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_CLOSE_SYSTEM_DIALOGS
(Reserved, not supported yet) Indicates that the user closes a temporary system dialog box.
- Value: **usual.event.CLOSE_SYSTEM_DIALOGS**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_ADDED
Indicates that a new application package has been installed on the device.
- Value: **usual.event.PACKAGE_ADDED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_REPLACED
(Reserved, not supported yet) Indicates that a later version of an installed application package has replaced the previous one on the device.
- Value: **usual.event.PACKAGE_REPLACED**
- Required subscriber permissions: none
## COMMON_EVENT_MY_PACKAGE_REPLACED
(Reserved, not supported yet) Indicates that a later version of your application package has replaced the previous one.
- Value: **usual.event.MY_PACKAGE_REPLACED**
......@@ -125,85 +111,67 @@ Indicates that an installed application has been uninstalled from the device wit
- Value: **usual.event.PACKAGE_REMOVED**
- Required subscriber permissions: none
## COMMON_EVENT_BUNDLE_REMOVED
(Reserved, not supported yet) Indicates that an installed bundle has been uninstalled from the device with the application data retained.
- Value: **usual.event.BUNDLE_REMOVED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_FULLY_REMOVED
(Reserved, not supported yet) Indicates that an installed application, including both the application data and code, has been completely uninstalled from the device.
- Value: **usual.event.PACKAGE_FULLY_REMOVED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_CHANGED
Indicates that an application package has been changed (for example, an ability in the package has been enabled or disabled).
- Value: **usual.event.PACKAGE_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_RESTARTED
## [COMMON_EVENT_PACKAGE_RESTARTED](./common_event/commonEvent-ability.md)
Indicates that the user closed all processes of the application and restarted the application.
- Value: **usual.event.PACKAGE_RESTARTED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_DATA_CLEARED
## [COMMON_EVENT_PACKAGE_DATA_CLEARED](./common_event/commonEvent-ability.md)
Indicates that the user cleared the application package data.
- Value: **usual.event.PACKAGE_DATA_CLEARED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_CACHE_CLEARED<sup>9+</sup>
Indicates that the user cleared the application package cache.
- Value: **usual.event.PACKAGE_CACHE_CLEARED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGES_SUSPENDED
(Reserved, not supported yet) Indicates that application HAP files are suspended.
- Value: **usual.event.PACKAGES_SUSPENDED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGES_UNSUSPENDED
(Reserved, not supported yet) Indicates that application HAP files are not suspended (restored from the suspended state).
- Value: **usual.event.PACKAGES_UNSUSPENDED**
- Required subscriber permissions: none
## COMMON_EVENT_MY_PACKAGE_SUSPENDED
Indicates that an application HAP file is suspended.
- Value: **usual.event.MY_PACKAGE_SUSPENDED**
- Required subscriber permissions: none
## COMMON_EVENT_MY_PACKAGE_UNSUSPENDED
Indicates that an application HAP file is not suspended.
- Value: **usual.event.MY_PACKAGE_UNSUSPENDED**
- Required subscriber permissions: none
## COMMON_EVENT_UID_REMOVED
(Reserved, not supported yet) Indicates that a user ID has been removed from the system.
- Value: **usual.event.UID_REMOVED**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_FIRST_LAUNCH
(Reserved, not supported yet) Indicates that an installed application is started for the first time.
- Value: **usual.event.PACKAGE_FIRST_LAUNCH**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_NEEDS_VERIFICATION
(Reserved, not supported yet) Indicates that an application requires system verification.
- Value: **usual.event.PACKAGE_NEEDS_VERIFICATION**
- Required subscriber permissions: none
## COMMON_EVENT_PACKAGE_VERIFIED
(Reserved, not supported yet) Indicates that an application has been verified by the system.
- Value: **usual.event.PACKAGE_VERIFIED**
......@@ -215,91 +183,76 @@ Indicates that an application HAP file is not suspended.
- Value: **usual.event.EXTERNAL_APPLICATIONS_AVAILABLE**
- Required subscriber permissions: none
## COMMON_EVENT_EXTERNAL_APPLICATIONS_UNAVAILABLE
(Reserved, not supported yet) Indicates that applications installed on the external storage are not available for the system.
- Value: **usual.event.EXTERNAL_APPLICATIONS_UNAVAILABLE**
- Required subscriber permissions: none
## COMMON_EVENT_CONFIGURATION_CHANGED
(Reserved, not supported yet) Indicates that the device state (for example, orientation and locale) has changed.
- Value: **usual.event.CONFIGURATION_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_LOCALE_CHANGED
(Reserved, not supported yet) Indicates that the device locale has changed.
- Value: **usual.event.LOCALE_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_MANAGE_PACKAGE_STORAGE
(Reserved, not supported yet) Indicates that the device storage is insufficient.
- Value: **usual.event.MANAGE_PACKAGE_STORAGE**
- Required subscriber permissions: none
## COMMON_EVENT_DRIVE_MODE
(Reserved, not supported yet) Indicates that the system is in driving mode.
- Value: **common.event.DRIVE_MODE**
- Required subscriber permissions: none
## COMMON_EVENT_HOME_MODE
(Reserved, not supported yet) Indicates that the system is in home mode.
- Value: **common.event.HOME_MODE**
- Required subscriber permissions: none
## COMMON_EVENT_OFFICE_MODE
(Reserved, not supported yet) Indicates that the system is in office mode.
- Value: **common.event.OFFICE_MODE**
- Required subscriber permissions: none
## COMMON_EVENT_USER_STARTED
(Reserved, not supported yet) Indicates that the user has been started.
- Value: **usual.event.USER_STARTED**
- Required subscriber permissions: none
## COMMON_EVENT_USER_BACKGROUND
(Reserved, not supported yet) Indicates that the user has been brought to the background.
- Value: **usual.event.USER_BACKGROUND**
- Required subscriber permissions: none
## COMMON_EVENT_USER_FOREGROUND
(Reserved, not supported yet) Indicates that the user has been brought to the foreground.
- Value: **usual.event.USER_FOREGROUND**
- Required subscriber permissions: none
## COMMON_EVENT_USER_SWITCHED
Indicates that user switching is in progress.
- Value: **usual.event.USER_SWITCHED**
- Required subscriber permissions: ohos.permission.MANAGE_LOCAL_ACCOUNTS
## COMMON_EVENT_USER_STARTING
(Reserved, not supported yet) Indicates that the user is being started.
- Value: **usual.event.USER_STARTING**
- Required subscriber permissions: ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS
## COMMON_EVENT_USER_UNLOCKED
(Reserved, not supported yet) Indicates that the credential-encrypted storage has been unlocked for the current user after the device is restarted.
- Value: **usual.event.USER_UNLOCKED**
- Required subscriber permissions: none
## COMMON_EVENT_USER_STOPPING
(Reserved, not supported yet) Indicates that the user is going to be stopped.
- Value: **usual.event.USER_STOPPING**
- Required subscriber permissions: ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS
## COMMON_EVENT_USER_STOPPED
(Reserved, not supported yet) Indicates that the user has been stopped.
- Value: **usual.event.USER_STOPPED**
......@@ -665,11 +618,15 @@ Indicates that the system charging type has changed. This event is available onl
- Value: **usual.event.CHARGE_TYPE_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_DEVICE_IDLE_MODE_CHANGED
## [COMMON_EVENT_DEVICE_IDLE_MODE_CHANGED](./common_event/commonEvent-resourceschedule.md)
(Reserved, not supported yet) Indicates that the system idle mode has changed.
- Value: **usual.event.DEVICE_IDLE_MODE_CHANGED**
- Required subscriber permissions: none
## [COMMON_EVENT_DEVICE_IDLE_EXEMPTION_LIST_UPDATED<sup>10+<sup>](./common_event/commonEvent-resourceschedule.md)
Indicates that the exemption list for resource usage restrictions has been updated in idle mode. This event is for system applications only.
- Value: **usual.event.DEVICE_IDLE_EXEMPTION_LIST_UPDATED**
- Required subscriber permissions: none
## COMMON_EVENT_POWER_SAVE_MODE_CHANGED
Indicates that the system power saving mode has changed.
......@@ -766,61 +723,51 @@ Indicates that a user has been removed from the system.
- Value: **common.event.IVI_VOLTAGE_RECOVERY**
- Required subscriber permissions: none
## COMMON_EVENT_IVI_TEMPERATURE_RECOVERY
(Reserved, not supported yet) Indicates that the temperature of the IVI system is restored to normal.
- Value: **common.event.IVI_TEMPERATURE_RECOVERY**
- Required subscriber permissions: none
## COMMON_EVENT_IVI_ACTIVE
(Reserved, not supported yet) Indicates that the battery service of the IVI system is active.
- Value: **common.event.IVI_ACTIVE**
- Required subscriber permissions: none
## COMMON_EVENT_USB_STATE<sup>9+</sup>
Indicates that the USB device state has changed.
- Value: **usual.event.hardware.usb.action.USB_STATE**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_USB_PORT_CHANGED<sup>9+</sup>
Indicates that the USB port state of the device has changed.
- Value: **usual.event.hardware.usb.action.USB_PORT_CHANGED**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_USB_DEVICE_ATTACHED
Indicates that a USB device has been attached to the device functioning as a USB host.
- Value: **usual.event.hardware.usb.action.USB_DEVICE_ATTACHED**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_USB_DEVICE_DETACHED
Indicates that a USB device has been detached from the device functioning as a USB host.
- Value: **usual.event.hardware.usb.action.USB_DEVICE_DETACHED**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_USB_ACCESSORY_ATTACHED
(Reserved, not supported yet) Indicates that a USB accessory was attached.
- Value: **usual.event.hardware.usb.action.USB_ACCESSORY_ATTACHED**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_USB_ACCESSORY_DETACHED
(Reserved, not supported yet) Indicates that a USB accessory was detached.
- Value: **usual.event.data.DISK_MOUNTED**
- Required subscriber permissions: none
For details, see [Common Events of the USB Subsystem](common_event/commonEvent-usb.md).
## COMMON_EVENT_DISK_REMOVED
(Reserved, not supported yet) Indicates that an external storage device was removed.
- Value: **usual.event.data.DISK_BAD_REMOVAL**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_DISK_UNMOUNTED
(Reserved, not supported yet) Indicates that an external storage device was unmounted.
- Value: **usual.event.data.DISK_UNMOUNTABLE**
......@@ -838,92 +785,77 @@ Indicates that a USB device has been detached from the device functioning as a U
- Value: usual.event.data.DISK_REMOVED
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_DISK_UNMOUNTABLE
(Reserved, not supported yet) Indicates that an external storage device is unmountable when the card is inserted.
- Value: **usual.event.data.DISK_UNMOUNTED**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_DISK_EJECT
(Reserved, not supported yet) Indicates that an external storage device was ejected (at the software level).
- Value: **usual.event.data.DISK_EJECT**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VOLUME_REMOVED<sup>9+</sup>
Indicates that an external storage device was removed.
- Value: **usual.event.data.VOLUME_REMOVED**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VOLUME_UNMOUNTED<sup>9+</sup>
Indicates that an external storage device was unmounted.
- Value: **usual.event.data.VOLUME_UNMOUNTED**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VOLUME_MOUNTED<sup>9+</sup>
Indicates that an external storage device was mounted.
- Value: **usual.event.data.VOLUME_MOUNTED**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VOLUME_BAD_REMOVAL<sup>9+</sup>
Indicates that an external storage device was removed without being unmounted.
- Value: **usual.event.data.VOLUME_BAD_REMOVAL**
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VOLUME_EJECT<sup>9+</sup>
Indicates that an external storage device was ejected (at the software level).
- Value: usual.event.data.VOLUME_EJECT
- Required subscriber permissions: ohos.permission.STORAGE_MANAGER
## COMMON_EVENT_VISIBLE_ACCOUNTS_UPDATED
(Reserved, not supported yet) Indicates that the account visibility changed.
- Value: **usual.event.data.VISIBLE_ACCOUNTS_UPDATED**
- Required subscriber permissions: ohos.permission.GET_APP_ACCOUNTS
## COMMON_EVENT_ACCOUNT_DELETED
(Reserved, not supported yet) Indicates that an account was deleted.
- Value: **usual.event.data.ACCOUNT_DELETED**
- Required subscriber permissions: ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS
## COMMON_EVENT_FOUNDATION_READY
(Reserved, not supported yet) Indicates that the foundation is ready.
- Value: **usual.event.data.FOUNDATION_READY**
- Required subscriber permissions: ohos.permission.RECEIVER_STARTUP_COMPLETED
## COMMON_EVENT_AIRPLANE_MODE_CHANGED
Indicates that the airplane mode of the device has changed.
- Value: **usual.event.AIRPLANE_MODE**
- Required subscriber permissions: none
## COMMON_EVENT_SPLIT_SCREEN
Indicates that the screen has been split.
- Value: **usual.event.SPLIT_SCREEN**
- Required subscriber permissions: ohos.permission.RECEIVER_SPLIT_SCREEN
## COMMON_EVENT_SLOT_CHANGE<sup>9+</sup>
Indicates that the notification slot has been updated.
- Value: **usual.event.SLOT_CHANGE**
- Required subscriber permissions: ohos.permission.NOTIFICATION_CONTROLLER
## COMMON_EVENT_SPN_INFO_CHANGED<sup>9+</sup>
Indicates that the SPN displayed has been updated.
- Value: **usual.event.SPN_INFO_CHANGED**
- Required subscriber permissions: none
## COMMON_EVENT_QUICK_FIX_APPLY_RESULT<sup>9+</sup>
## [COMMON_EVENT_QUICK_FIX_APPLY_RESULT<sup>9+<sup>](./common_event/commonEvent-ability.md)
Indicates the result of applying a quick fix to the application.
- Value: **usual.event.QUICK_FIX_APPLY_RESULT**
- Required subscriber permissions: none
......@@ -1049,3 +981,6 @@ Indicates that the screen is unlocked.
- Value: **usual.event.SCREEN_UNLOCKED**
- Required subscriber permissions: none
## [COMMON_EVENT_QUICK_FIX_REVOKE_RESULT<sup>10+<sup>](./common_event/commonEvent-ability.md#common_event_quick_fix_revoke_result10)
ָIndicates the result of revoking a quick fix to the application.
\ No newline at end of file
# Common Events
- [Common Events of the Ability Subsystem](commonEvent-ability.md)
- [Common Events of the Bundle Management Subsystem](commonEvent-bundleManager.md)
- [Common Events of the Notification Service](commonEvent-ans.md)
- [Common Events of the Resource Scheduling Subsystem](commonEvent-resourceschedule.md)
- [Common Events of the Telephony Subsystem](commonEvent-telephony.md)
- [Common Events of the USB Subsystem](commonEvent-usb.md)
# Common Events of the Ability Subsystem
This document lists the common system events provided by the Ability subsystem to applications.
## COMMON_EVENT_BOOT_COMPLETED
Indicates that the user has finished the boot process.
- Constant value: "usual.event.BOOT_COMPLETED"
- Required subscriber permissions: ohos.permission.RECEIVER_STARTUP_COMPLETED
When the specified user finishes the boot process on the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_PACKAGE_RESTARTED
Indicates that the user has restarted the application package and killed all its processes.
- Constant value: "usual.event.PACKAGE_RESTARTED"
- Required subscriber permissions: none
When the specified user restarts the application and kills all its processes, the event notification service is triggered to publish this event.
## COMMON_EVENT_PACKAGE_DATA_CLEARED
Indicates that the user cleared the application package data.
- Constant value: "usual.event.PACKAGE_DATA_CLEARED"
- Required subscriber permissions: none
When the specified user clears the application package data on the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_QUICK_FIX_APPLY_RESULT<sup>9+</sup>
Indicates the result of applying a quick fix to the application.
- Constant value: "usual.event.QUICK_FIX_APPLY_RESULT"
- Required subscriber permissions: none
When the specified user applies a quick fix to the application on the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_QUICK_FIX_REVOKE_RESULT<sup>10+</sup>
Indicates the result of revoking a quick fix to the application.
- Constant value: "usual.event.QUICK_FIX_REVOKE_RESULT"
- Required subscriber permissions: none
When a quick fix to the application is revoked on the device, the event notification service is triggered to publish this event.
# Common Events of the Resource Scheduling Subsystem
This document lists the common system events provided by the resource scheduling subsystem to applications. Applications can use [APIs](../js-apis-commonEventManager.md) to subscribe to common system events.
## COMMON_EVENT_DEVICE_IDLE_MODE_CHANGED
Indicates that the system idle mode has changed.
- Constant value: "usual.event.DEVICE_IDLE_MODE_CHANGED"
- Required subscriber permissions: none
When the user does not use the device for the specified period of time and the screen is turned off, the system delays the CPU and network access by background applications, and the event notification service is triggered to publish this event.
APIs related to this event: **deviceStandby**.
## COMMON_EVENT_DEVICE_IDLE_EXEMPTION_LIST_UPDATED
Indicates that the exemption list for resource usage restrictions has been updated in idle mode.
- Constant value: "usual.event.DEVICE_IDLE_EXEMPTION_LIST_UPDATED"
- Required subscriber permissions: none
When the exemption list for resource usage restrictions is updated, the event notification service is triggered to publish this event.
Resources include application network access, Timer usage, and WorkScheduler task usage.
System applications can call JavaScript APIs to apply for removing resource usage restrictions.
APIs related to this event: **deviceStandby**.
# Common Events of the USB Subsystem
This document lists the common system events provided by the USB subsystem to applications. Applications can use [APIs](../js-apis-commonEventManager.md) to subscribe to common system events.
## COMMON_EVENT_USB_STATE
Indicates that the USB device state has changed.
- Constant value: "usual.event.hardware.usb.action.USB_STATE"
- Required subscriber permissions: none
When a USB device is connected to or disconnected from the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_USB_PORT_CHANGED
Indicates that the USB port state of the device has changed.
- Constant value: "usual.event.hardware.usb.action.USB_PORT_CHANGED"
- Required subscriber permissions: none
When the USB port status changes, the event notification service is triggered to publish this event.
APIs related to this event: **dataRole** parameter in [setPortRoles](../js-apis-usbManager.md#usbsetportroles).
## COMMON_EVENT_USB_DEVICE_ATTACHED
Indicates that a USB device has been attached to the device functioning as a USB host.
- Constant value: "usual.event.hardware.usb.action.USB_DEVICE_ATTACHED"
- Required subscriber permissions: none
When a USB device is attached, the event notification service is triggered to publish this event.
APIs related to this event: [USBDevice](../js-apis-usbManager.md#usbdevice).
## COMMON_EVENT_USB_DEVICE_DETACHED
Indicates that a USB device has been detached from the device functioning as a USB host.
- Constant value: "usual.event.hardware.usb.action.USB_DEVICE_DETACHED"
- Required subscriber permissions: none
When a USB device is deattached, the event notification service is triggered to publish this event.
APIs related to this event: [USBDevice](../js-apis-usbManager.md#usbdevice).
## COMMON_EVENT_USB_ACCESSORY_ATTACHED
(Reserved, not supported yet) Indicates that a USB accessory was attached.
- Constant value: "usual.event.hardware.usb.action.USB_ACCESSORY_ATTACHED"
- Required subscriber permissions: none
## COMMON_EVENT_USB_ACCESSORY_DETACHED
(Reserved, not supported yet) Indicates that a USB accessory was detached.
- Constant value: "usual.event.data.DISK_MOUNTED"
- Required subscriber permissions: none
......@@ -6,7 +6,7 @@ The **\<Span>** component is used to display inline text in the **\<Text>** comp
>
> This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
>
> Since API version 10, this component can inherit the attributes of the **\<Text>** parent component. That is, if no attribute is set for this component, it inherits the attributes (if set) of its parent component. The following attributes can be inherited: **fontColor**, **fontSize**, **fontStyle**, **fontWeight**, **decoration**, **letterSpacing**, **textCase**, **lineHeight**, and **fontfamily**.
> Since API version 10, this component can inherit the attributes of the **\<Text>** parent component. That is, if no attribute is set for this component, it inherits the attributes (if set) of its parent component. Only the following attributes can be inherited: **fontColor**, **fontSize**, **fontStyle**, **fontWeight**, **decoration**, **letterSpacing**, **textCase**, and **fontfamily**.
## Child Components
......
......@@ -24,7 +24,7 @@ StepperItem()
| -------- | -------- | -------- |
| prevLabel | string | Text label of the button on the left, which is not displayed on the first page. When the **\<Stepper>** contains more than one page, the default value for all pages except the first page is **Back**.|
| nextLabel | string | Text label of the button on the right. The default value is **Start** for the last page and **Next** for the other pages.|
| status | ItemState | Display status of **nextLabel** in the stepper.<br>Default value: **ItemState.Normal**|
| status | [ItemState](#itemstate) | Display status of **nextLabel** in the stepper. Optional.<br>Default value: **ItemState.Normal**|
## ItemState
......
......@@ -24,9 +24,9 @@ Video(value: {src?: string | Resource, currentProgressRate?: number | string | P
| Name | Type | Mandatory| Description |
| ------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
| src | string \| [Resource](ts-types.md) | No | Path of the video source, which can be a local path or a URL.<br>The video resources can be stored in the **video** or **rawfile** folder under **resources**.<br>The path can include a **dataability://** prefix, which indicates that the path is provided by a Data ability. For details about the path, see [Data Ability Development](../../application-models/dataability-overview.md).<br>**NOTE**<br>The supported video formats are MP4, MKV, WebM, and TS.|
| src | string \| [Resource](ts-types.md) | No | Path of the video source, which can be a local path or a URL.<br>The video resources can be stored in the **video** or **rawfile** folder under **resources**.<br>The path can include a **dataability://** prefix, which indicates that the path is provided by a Data ability. For details about the path, see [Data Ability Development](../../application-models/dataability-overview.md).<br>- Strings with the **file:///data/storage** prefix are supported, which are used to read resources in the application sandbox. Ensure that the application has the read permission to the files in the specified path.<br>**NOTE**<br>The supported video formats are MP4, MKV, WebM, and TS. |
| currentProgressRate | number \| string \| PlaybackSpeed<sup>8+</sup> | No | Video playback speed.<br>**NOTE**<br>The value of the number type can only be **0.75**, **1.0**, **1.25**, **1.75**, or **2.0**.<br>Default value: 1.0 \| PlaybackSpeed.Speed_Forward_1_00_X |
| previewUri | string \|PixelMap \| [Resource](ts-types.md) | No | Path of the preview image. (The PixelMap type is not supported currently.) |
| previewUri | string \|PixelMap \| [Resource](ts-types.md) | No | Path of the preview image. |
| controller | [VideoController](#videocontroller) | No | Video controller. |
## PlaybackSpeed<sup>8+</sup>
......
......@@ -3,12 +3,12 @@
The framework provides four pixel units, with vp as the reference data unit.
| Name | Description |
| ---- | ---------------------------------------- |
| px | Physical pixel unit of the screen. |
| vp | Pixel unit specific to the screen density. Pixels in this unit are converted into physical pixels of the screen based on the screen pixel density. This unit is used for values whose unit is not specified.|
| fp | Font pixel, which is similar to vp and varies according to the system font size. |
| lpx | Logical pixel unit of the window. It is the ratio of the actual screen width to the logical width (configured by **designWidth**). For example, if **designWidth** is set to **720** (default value), then 1lpx is equal to 2px for a screen with an actual width of 1440 physical pixels.|
| Name| Description |
| ---- | ------------------------------------------------------------ |
| px | Physical pixel unit of the screen. |
| vp | Pixel unit specific to the screen density. Pixels in this unit are converted into physical pixels of the screen based on the screen pixel density. This unit is used for values whose unit is not specified. On a screen with an actual width of 1440 physical pixels, 1 vp is approximately equal to 3 px.|
| fp | Font pixel, which is similar to vp and varies according to the system font size.|
| lpx | Logical pixel unit of the window. It is the ratio of the actual screen width to the logical width (configured by **designWidth**). For example, if **designWidth** is set to **720** (default value), then 1 lpx is equal to 2 px for a screen with an actual width of 1440 physical pixels.|
## Pixel Unit Conversion
......@@ -37,33 +37,71 @@ struct Example {
Flex({ wrap: FlexWrap.Wrap }) {
Column() {
Text("width(220)")
.width(220).height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width(220)
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width('220px')")
.width('220px').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White)
.width('220px')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
}.margin(5)
Column() {
Text("width('220vp')")
.width('220vp').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width('220vp')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width('220lpx') designWidth:720")
.width('220lpx').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width('220lpx')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("width(vp2px(220) + 'px')")
.width(vp2px(220) + 'px').height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12vp')
.width(vp2px(220) + 'px')
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12vp')
}.margin(5)
Column() {
Text("fontSize('12fp')")
.width(220).height(40).backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center).fontColor(Color.White).fontSize('12fp')
.width(220)
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12fp')
}.margin(5)
Column() {
Text("width(px2vp(220))")
.width(px2vp(220))
.height(40)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize('12fp')
}.margin(5)
}.width('100%')
}
......
# UI Development
- [ArkUI Overview](arkui-overview.md)
- ArkTS-based Declarative Development Paradigm
- [Overview](ui-ts-overview.md)
- [Declarative UI Development Guidelines](ui-ts-developing-intro.md)
- Declarative UI Development Examples
- [Creating a Simple Page](ui-ts-creating-simple-page.md)
- Building a Comprehensive Example
- [Building a Food Data Model](ui-ts-building-data-model.md)
- [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)
- Adding a Splash Screen Animation
- [Using the Drawing Feature](ui-ts-drawing-feature.md)
- [Using the Animation Feature](ui-ts-animation-feature.md)
- [Common Components](ui-ts-components-intro.md)
- Common Layout Development
- Adaptive Layouts
- [Linear Layout](ui-ts-layout-linear.md)
- [Statck Layout](ui-ts-layout-stack.md)
- [Flex Layout](ui-ts-layout-flex.md)
- [Grid Layout](ui-ts-layout-grid.md)
- Responsive Layouts
- [Grid Layout](ui-ts-layout-grid-container-new.md)
- [Media Query](ui-ts-layout-mediaquery.md)
- [Custom Component Lifecycle Callbacks](ui-ts-custom-component-lifecycle-callbacks.md)
- [Web Component Development](ui-ts-components-web.md)
- [Recommendations for Improving Performance](ui-ts-performance-improvement-recommendation.md)
- JavaScript-compatible Web-like Development Paradigm
- [Overview](ui-js-overview.md)
- Framework Overview
- [File Organization](js-framework-file.md)
- UI Development (ArkTS-based Declarative Development Paradigm)
- [UI Development (ArkTS-based Declarative Development Paradigm) Overview](arkts-ui-development-overview.md)
- Layout Development
- [Layout Overview](arkts-layout-development-overview.md)
- Building a Layout
- [Linear Layout](arkts-layout-development-linear.md)
- [Stack Layout](arkts-layout-development-stack-layout.md)
- [Flex Layout](arkts-layout-development-flex-layout.md)
- [Relative Layout](arkts-layout-development-relative-layout.md)
- [Responsive Grid Layout](arkts-layout-development-grid-layout.md)
- [Media Query](arkts-layout-development-media-query.md)
- [Creating a List](arkts-layout-development-create-list.md)
- [Creating a Grid](arkts-layout-development-create-grid.md)
- [Creating a Swiper](arkts-layout-development-create-looping.md)
- [Improving Layout Performance](arkts-layout-development-performance-boost.md)
- Adding a Component
- Adding a Common Component
- [Button](arkts-common-components-button.md)
- [Radio Button](arkts-common-components-radio-button.md)
- [Toggle](arkts-common-components-switch.md)
- [Progress Indicator](arkts-common-components-progress-indicator.md)
- [Text Display](arkts-common-components-text-display.md)
- [Text Input](arkts-common-components-text-input.md)
- [Custom Dialog Box](arkts-common-components-custom-dialog.md)
- [Video Playback](arkts-common-components-video-player.md)
- [XComponent](arkts-common-components-xcomponent.md)
- Adding a Bubble and Menu
- [Bubble](arkts-popup-and-menu-components-popup.md)
- [Menu](arkts-popup-and-menu-components-menu.md)
- Setting Page Routing and Component Navigation
- [Page Routing](arkts-routing.md)
- Component Navigation
- [Navigation](arkts-navigation-navigation.md)
- [Tabs](arkts-navigation-tabs.md)
- Using Graphics
- [Displaying Images](arkts-graphics-display.md)
- [Drawing Geometric Shapes](arkts-geometric-shape-drawing.md)
- [Drawing Custom Graphics on the Canvas](arkts-drawing-customization-on-canvas.md)
- Using Animation
- [Animation Overview](arkts-animation-overview.md)
- Animation Within a Page
- [Layout Update Animation](arkts-layout-update-animation.md)
- [Transition Animation Within a Component](arkts-transition-animation-within-component.md)
- [Spring Curve Animation](arkts-spring-animation.md)
- Animation Between Pages
- [Zoom Animation](arkts-zoom-animation.md)
- [Page Transition Animation](arkts-page-transition-animation.md)
- Using Interaction Events
- [Interaction Event Overview](arkts-event-overview.md)
- Universal Events
- [Touchscreen Event](arkts-common-events-touch-screen-event.md)
- [Keyboard and Mouse Event](arkts-common-events-device-input-event.md)
- [Focus Event](arkts-common-events-focus-event.md)
- Gesture Events
- [Gesture Binding](arkts-gesture-events-binding.md)
- [Single Gesture](arkts-gesture-events-single-gesture.md)
- [Combined Gestures](arkts-gesture-events-combined-gestures.md)
- [Recommendations for Improving Performance](arkts-performance-improvement-recommendation.md)
- UI Development (JavaScript-compatible Web-like Development Paradigm)
- [UI Development (JavaScript-compatible Web-like Development Paradigm) Overview](ui-js-overview.md)
- Framework Overview
- [File Organization](js-framework-file.md)
- ["js" Tag](js-framework-js-tag.md)
- [app.js](js-framework-js-file.md)
- Syntax
......
# Animation Overview
The principle of animation is that the UI appearance is changed for multiple times within a period of time. Because human eyes retain persistence of vision, what you finally see is a continuous animation. A change of the UI is called an animation frame, which corresponds to a screen refresh. An important indicator that determines the animation smoothness is the frame rate (FPS), that is, the number of animation frames per second. The higher the frame rate, the smoother the animation.
In ArkUI, an animation is generated by changing the attribute value and specifying the animation parameters. Animation parameters include animation duration, change rule (that is, curve), and more. After the attribute value changes, the original state is transited to the new state according to the animation parameters. In this way, an animation is formed.
The animation capability provided by ArkUI can be classified into intra-page animation and inter-page animation based on the page classification mode. As shown in the following figure, an animation on a page refers to an animation that can occur on a page, and an animation between pages refers to an animation that occurs only with redirection between pages.
**Figure 1** Animation by page
![en-us_image_0000001562700385](figures/en-us_image_0000001562700385.png)
By capability, the animation can be divided into three parts: attribute animation, explicit animation, and transition animation, as shown in the following figure.
**Figure 2** Animation classified by basic capability
![en-us_image_0000001562820753](figures/en-us_image_0000001562820753.png)
This topic will introduce you to the usage and precautions of animations by the preceding classification and use cases.
# Button
The **\<Button>** component is usually activated by user clicks to perform a specific action. Buttons are classified as capsule, circle, or normal buttons. When used as a container, the **\<Button>** component accepts child components such as text and images. For details, see [Button](../reference/arkui-ts/ts-basic-components-button.md).
## Creating a Button
You can create a button that contains or does not contain child components.
- Create a button that does not contain child components.
```ts
Button(label?: string, options?: { type?: ButtonType, stateEffect?: boolean })
```
Creates a button that does not contain child components. In this API, **label** indicates the button text, **type** indicates the button type, and **stateEffect** specifies whether to set pressed effect on the click of the button.
```ts
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.borderRadius(8)
.backgroundColor(0x317aff)
.width(90)
.height(40)
```
![en-us_image_0000001562820757](figures/en-us_image_0000001562820757.png)
- Create a button that contains child components.
```ts
Button(options?: {type?: ButtonType, stateEffect?: boolean})
```
Creates a button that contains a single child component, which can either be a [basic component](../reference/arkui-ts/ts-basic-components-blank.md) or a [container component](../reference/arkui-ts/ts-container-ability-component.md).
```ts
Button({ type: ButtonType.Normal, stateEffect: true }) {
Row() {
Image($r('app.media.loading')).width(20).height(40).margin({ left: 12 })
Text('loading').fontSize(12).fontColor(0xffffff).margin({ left: 5, right: 12 })
}.alignItems(VerticalAlign.Center)
}.borderRadius(8).backgroundColor(0x317aff).width(90).height(40)
```
![en-us_image_0000001511421216](figures/en-us_image_0000001511421216.png)
## Setting the Button Type
Use the **type** parameter to set the button type to **Capsule**, **Circle**, or **Normal**.
- Capsule button (default type)
Buttons of this type have rounded corners whose radius is automatically set to half of the button height. The rounded corners cannot be reset through the **borderRadius** attribute.
```ts
Button('Disable', { type: ButtonType.Capsule, stateEffect: false })
.backgroundColor(0x317aff)
.width(90)
.height(40)
```
![en-us_image_0000001511421208](figures/en-us_image_0000001511421208.png)
- Circle button
Buttons of this type are round. The rounded corners cannot be reset through the **borderRadius** attribute.
```ts
Button('Circle', { type: ButtonType.Circle, stateEffect: false })
.backgroundColor(0x317aff)
.width(90)
.height(90)
```
![en-us_image_0000001511740428](figures/en-us_image_0000001511740428.png)
- Normal button
Buttons of this type have rounded corners set to 0. The rounded corners can be reset through the **borderRadius** attribute.
```ts
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.borderRadius(8)
.backgroundColor(0x317aff)
.width(90)
.height(40)
```
![en-us_image_0000001563060641](figures/en-us_image_0000001563060641.png)
## Setting Styles
- Set the border radius:
In general cases, you can use universal attributes to define the button styles. For example, you can use the **borderRadius** attribute to set the border radius.
```ts
Button('circle border', { type: ButtonType.Normal })
.borderRadius(20)
.height(40)
```
![en-us_image_0000001511900392](figures/en-us_image_0000001511900392.png)
- The **Font** type is used to set the text style.
Add a font style for text displayed on the button.
```ts
Button('font style', { type: ButtonType.Normal })
.fontSize(20)
.fontColor(Color.Pink)
.fontWeight(800)
```
![en-us_image_0000001511580828](figures/en-us_image_0000001511580828.png)
- Set the background color:
You can do so by adding the **backgroundColor** attribute.
```ts
Button('background color').backgroundColor(0xF55A42)
```
![en-us_image_0000001562940477](figures/en-us_image_0000001562940477.png)
- Assign a function to the button:
In this example, the delete function is assigned to the button.
```ts
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($r('app.media.ic_public_delete_filled')).width(30).height(30)
}.width(55).height(55).margin({ left: 20 }).backgroundColor(0xF55A42)
```
![en-us_image_0000001511740436](figures/en-us_image_0000001511740436.png)
## Adding Events
The **\<Button>** component is usually used to trigger actions. You can bind the **onClick** event to the button to have it respond with custom behavior after being clicked.
```ts
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.onClick(()=>{
console.info('Button onClick')
})
```
## Example Scenario
- Using the Button for Startup
You can use the button for any UI element that involves the startup operation. The button triggers the predefined event based on the user's operation. For example, you can use a button in the **\<List>** container to redirect the user to another page.
```ts
// xxx.ets
import router from '@ohos.router';
@Entry
@Component
struct ButtonCase1 {
build() {
List({ space: 4 }) {
ListItem() {
Button("First").onClick(() => {
router.pushUrl({ url: 'pages/first_page' })
})
.width('100%')
}
ListItem() {
Button("Second").onClick(() => {
router.pushUrl({ url: 'pages/second_page' })
})
.width('100%')
}
ListItem() {
Button("Third").onClick(() => {
router.pushUrl({ url: 'pages/third_page' })
})
.width('100%')
}
}
.listDirection(Axis.Vertical)
.backgroundColor(0xDCDCDC).padding(20)
}
}
```
![en-us_image_0000001562700393](figures/en-us_image_0000001562700393.png)
- Use the button for submitting forms:
On the user login/registration page, you can use a button to submit a login or registration request.
```ts
// xxx.ets
@Entry
@Component
struct ButtonCase2 {
build() {
Column() {
TextInput({ placeholder: 'input your username' }).margin({ top: 20 })
TextInput({ placeholder: 'input your password' }).type(InputType.Password).margin({ top: 20 })
Button('Register').width(300).margin({ top: 20 })
.onClick(() => {
// Operation
})
}.padding(20)
}
}
```
![en-us_image_0000001562940473](figures/en-us_image_0000001562940473.png)
- Configure the button to float:
The button can remain floating when the user swipes on the screen.
```ts
// xxx.ets
@Entry
@Component
struct HoverButtonExample {
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
build() {
Stack() {
List({ space: 20, initialIndex: 0 }) {
ForEach(this.arr, (item) => {
ListItem() {
Text('' + item)
.width('100%').height(100).fontSize(16)
.textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)
}
}, item => item)
}.width('90%')
Button() {
Image($r('app.media.ic_public_add'))
.width(50)
.height(50)
}
.width(60)
.height(60)
.position({x: '80%', y: 600})
.shadow({radius: 10})
.onClick(() => {
// Operation
})
}
.width('100%')
.height('100%')
.backgroundColor(0xDCDCDC)
.padding({ top: 5 })
}
}
```
![GIF](figures/GIF.gif)
# Custom Dialog Box
A custom dialog box is a dialog box you customize by using APIs of the **CustomDialogController** class. It can be used for user interactions, showing an ad, prize, alert, software update message, and more. For details, see [Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md).
## Creating a Custom Dialog Box
1. Use the \@CustomDialog decorator to create a custom dialog box.
2. Set the content for the \@CustomDialog decorated dialog box.
```ts
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
build() {
Column() {
Text ('I am content')
.fontSize(20)
.margin({ top: 10, bottom: 10 })
}
}
}
```
3. Create a builder that is bound to the decorator.
```ts
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({}),
})
```
4. Click the component bound to the **onClick** event to display the dialog box.
```ts
Flex({justifyContent:FlexAlign.Center}){
Button('click me')
.onClick(() => {
this.dialogController.open()
})
}.width('100%')
```
![en-us_image_0000001562700493](figures/en-us_image_0000001562700493.png)
## Interaction with Custom Dialog Box
Custom dialog boxes can be used for data interactions to complete a series of response operations.
1. Add button operations to the \@CustomDialog decorator and add the creation of data functions.
```ts
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
cancel: () => void
confirm: () => void
build() {
Column() {
Text('I am content') .fontSize(20).margin({ top: 10, bottom: 10 })
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('cancel')
.onClick(() => {
this.controller.close()
this.cancel()
}).backgroundColor(0xffffff).fontColor(Color.Black)
Button('confirm')
.onClick(() => {
this.controller.close()
this.confirm()
}).backgroundColor(0xffffff).fontColor(Color.Red)
}.margin({ bottom: 10 })
}
}
}
```
2. Receive the page in the builder and create corresponding function operations.
```ts
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
}),
alignment: DialogAlignment.Default, // Set the alignment mode of the dialog box. By default, the dialog box is displayed at the bottom.
})
onCancel() {
console.info('Callback when the first button is clicked')
}
onAccept() {
console.info('Callback when the second button is clicked')
}
```
![en-us_image_0000001511421320](figures/en-us_image_0000001511421320.png)
# Progress Indicator
The **\<Progress>** component is used to provide a progress indicator that displays the progress of an operation. For details, see [Progress](../reference/arkui-ts/ts-basic-components-progress.md).
## Creating a Progress Indicator
You can create a progress indicator by calling the following API:
```ts
Progress(options: {value: number, total?: number, type?: ProgressType})
```
Creates a progress bar indicator. In this API, **value** indicates the initial progress, **total** indicates the total progress, and **type** indicates the style of the progress indicator.
```ts
Progress({ value: 24, total: 100, type: ProgressType.Linear }) // Create a linear progress indicator whose total progress is 100 and initial progress is 24.
```
![create](figures/create.png)
## Setting the Progress Indicator Style
Progress indicators come in five styles. When creating a progress indicator, you can specify its style by setting the **ProgressType** parameter to any of the following: **ProgressType.Linear** (linear style), **ProgressType.Ring** (indeterminate ring style), **ProgressType.ScaleRing** (determinate ring style), **ProgressType.Eclipse** (eclipse style), and **ProgressType.Capsule** (capsule style).
- Linear style (default style)
>**NOTE**
>
> Since API version 9, the progress indicator adaptively switches to the vertical layout if the height is greater than the width and remains the horizontal layout if the height is equal to the width.
```ts
Progress({ value: 20, total: 100, type: ProgressType.Linear }).width(200).height(50)
Progress({ value: 20, total: 100, type: ProgressType.Linear }).width(50).height(200)
```
![en-us_image_0000001562700417](figures/en-us_image_0000001562700417.png)
- Indeterminate ring style
```ts
// The progress indicator in the indeterminate ring style on the left: Retain its default settings for the foreground color (blue) and stroke width (2.0 vp).
Progress({ value: 40, total: 150, type: ProgressType.Ring }).width(100).height(100)
// The right progress indicator in the indeterminate ring style on the right.
Progress({ value: 40, total: 150, type: ProgressType.Ring }).width(100).height(100)
.color(Color.Grey) // Set the foreground color to gray.
.style({ strokeWidth: 15}) // Set the stroke width to 15.0 vp.
```
![progress_ring](figures/progress_ring.png)
- Determinate ring style
```ts
Progress({ value: 20, total: 150, type: ProgressType.ScaleRing }).width(100).height(100)
.backgroundColor(Color.Black)
.style({ scaleCount: 20, scaleWidth: 5 }) // Set the total number of scales to 20 and the scale width to 5 vp.
Progress({ value: 20, total: 150, type: ProgressType.ScaleRing }).width(100).height(100)
.backgroundColor(Color.Black)
.style({ strokeWidth: 15, scaleCount: 20, scaleWidth: 5 }) // Set the stroke width to 15, the total number of scales to 20, and the scale width to 5 vp.
Progress({ value: 20, total: 150, type: ProgressType.ScaleRing }).width(100).height(100)
.backgroundColor(Color.Black)
.style({ strokeWidth: 15, scaleCount: 20, scaleWidth: 3 }) // Set the stroke width to 15, the total number of scales to 20, and the scale width to 3 vp.
```
![progress_scalering](figures/progress_scalering.png)
- Eclipse style
```ts
// The progress indicator in the eclipse style on the left: Retain its default settings for the foreground color (blue).
Progress({ value: 10, total: 150, type: ProgressType.Eclipse }).width(100).height(100)
// The progress indicator in the eclipse style on the right: Set its foreground color to gray.
Progress({ value: 20, total: 150, type: ProgressType.Eclipse }).color(Color.Grey).width(100).height(100)
```
![progress_circle](figures/progress_circle.png)
- Capsule style
>**NOTE**
>
>- At both ends, the progress indicator in the capsule style works in a same manner as that in the eclipse style.
>- In the middle part of the capsule, the progress indicator works in a same manner as the linear style.
>
>- If the height is greater than the width, the progress indicator adaptively switches to the vertical layout.
```ts
Progress({ value: 10, total: 150, type: ProgressType.Capsule }).width(100).height(50)
Progress({ value: 20, total: 150, type: ProgressType.Capsule }).width(50).height(100).color(Color.Grey)
Progress({ value: 50, total: 150, type: ProgressType.Capsule }).width(50).height(100).backgroundColor(Color.Black)
```
![progress_captule](figures/progress_captule.png)
## Example Scenario
In this example, the progress of the **\<Progress>** component is updated by clicking the button. After the button is clicked, the value of **progressValue** is incremented and passed to the **\<Progress>** component, which is then updated accordingly.
```ts
@Entry
@Component
struct ProgressCase1 {
@State progressValue: number = 0 // Set the initial progress of the progress indicator to 0.
build() {
Column() {
Column() {
Progress({value:0, total:100, type:ProgressType.Capsule}).width(200).height(50)
.style({strokeWidth:50}).value(this.progressValue)
Row().width('100%').height(5)
Button ("Progress + 5")
.onClick(()=>{
this.progressValue += 5
if (this.progressValue > 100){
this.progressValue = 0
}
})
}
}.width('100%').height('100%')
}
}
```
![progress](figures/progress.gif)
# Radio Button
The **\<Radio>** component allows users to select from a set of mutually exclusive options. Only one radio button in a given group can be selected at the same time. For details, see [Radio](../reference/arkui-ts/ts-basic-components-radio.md).
## Creating a Radio Button
You can create a radio button by calling the following API:
```ts
Radio(options: {value: string, group: string})
```
Creates a radio button. In this API, **value** indicates the name of the radio button, and **group** indicates the name of the group to which the radio button belongs. You can use the **checked** attribute of the radio button to specify whether it is selected. The value **true** means that the radio button is selected. The color and shape cannot be customized for the radio button.
```ts
Radio({ value: 'Radio1', group: 'radioGroup' })
.checked(false)
Radio({ value: 'Radio2', group: 'radioGroup' })
.checked(true)
```
![en-us_image_0000001562820821](figures/en-us_image_0000001562820821.png)
## Adding Events
The **\<Radio>** component supports the [universal events](../reference/arkui-ts/ts-universal-events-click.md). In addition, it can be bound to the **onChange** event so that it responds with custom behavior after being selected.
```ts
Radio({ value: 'Radio1', group: 'radioGroup' })
.onChange((isChecked: boolean) => {
if(isChecked) {
// Operation
}
})
Radio({ value: 'Radio2', group: 'radioGroup' })
.onChange((isChecked: boolean) => {
if(isChecked) {
// Operation
}
})
```
## Example Scenario
In this example, the **\<Radio>** components are used to switch between sound modes.
```ts
// xxx.ets
import promptAction from '@ohos.promptAction';
@Entry
@Component
struct RadioExample {
build() {
Row() {
Column() {
Radio({ value: 'Radio1', group: 'radioGroup' }).checked(true)
.height(50)
.width(50)
.onChange((isChecked: boolean) => {
if(isChecked) {
// Switch to the ringing mode.
promptAction.showToast({ message: 'Ringing mode.' })
}
})
Text('Ringing')
}
Column() {
Radio({ value: 'Radio2', group: 'radioGroup' })
.height(50)
.width(50)
.onChange((isChecked: boolean) => {
if(isChecked) {
// Switch to the vibration mode.
promptAction.showToast({ message: 'Vibration mode.' })
}
})
Text('Vibration')
}
Column() {
Radio({ value: 'Radio3', group: 'radioGroup' })
.height(50)
.width(50)
.onChange((isChecked: boolean) => {
if(isChecked) {
// Switch to the silent mode.
promptAction.showToast({ message: 'Silent mode.' })
}
})
Text('Silent')
}
}.height('100%').width('100%').justifyContent(FlexAlign.Center)
}
}
```
![en-us_image_0000001562700457](figures/en-us_image_0000001562700457.png)
# Text Display
The **\<Text>** component is used to display a piece of textual information. For details, see [Text](../reference/arkui-ts/ts-basic-components-text.md).
## Creating Text
You can create text in either of the following ways:
- Entering strings
```ts
Text ('I am a piece of text')
```
![en-us_image_0000001563060685](figures/en-us_image_0000001563060685.png)
- Referencing Resource objects
You can use **$r** to create a **Resource** object to reference resources in **/resources/base/element/string.json**.
```ts
Text($r('app.string.module_desc'))
.baselineOffset(0)
.fontSize(30)
.border({ width: 1 })
.padding(10)
.width(300)
```
![en-us_image_0000001511580872](figures/en-us_image_0000001511580872.png)
## Adding Child Components
The **\<Text>** component accepts \<[Span](../reference/arkui-ts/ts-basic-components-span.md)> as its child component. You can add one or more **\<Span>** child components to a **\<Text>** component to display a piece of information, such as the product description and statement of commitment.
- Creating a \<Span> Component
The **\<Span>** component works only when included in a **\<Text>** component. If both the **\<Span>** and **\<Text>** components have text configured, the text of the **\<Span>** overwrites that of the **\<Text>** component.
```ts
Text (' I'm Text') {
Span (' I'm Span')
}
.padding(10)
.borderWidth(1)
```
![en-us_image_0000001562700441](figures/en-us_image_0000001562700441.png)
- Set the text decorative line.
Use the **decoration** attribute to set the style and color of the text decorative line.
```ts
Text() {
Span('I'm Span1,') .fontSize (16).fontColor (Color.Grey)
.decoration({ type: TextDecorationType.LineThrough, color: Color.Red })
Span('I'm Span2').fontColor (Color.Blue).fontSize (16)
.fontStyle(FontStyle.Italic)
.decoration({ type: TextDecorationType.Underline, color: Color.Black })
Span('I'm Span3').fontSize(16).fontColor(Color.Grey)
.decoration({ type: TextDecorationType.Overline, color: Color.Green })
}
.borderWidth(1)
.padding(10)
```
![en-us_image_0000001562700437](figures/en-us_image_0000001562700437.png)
- Use the **textCase** attribute to set the text case.
```ts
Text() {
Span('I am Upper-span').fontSize(12)
.textCase(TextCase.UpperCase)
}
.borderWidth(1)
.padding(10)
```
![en-us_image_0000001562940525](figures/en-us_image_0000001562940525.png)
- Adding Events
The **\<Span>** component does not have size information. Therefore, only the **onClick** event is supported.
```ts
Text() {
Span('I am Upper-span').fontSize(12)
.textCase(TextCase.UpperCase)
.onClick(()=>{
console.info (' I'm Span - onClick')
})
}
```
## Setting Styles
- Use the **textAlign** attribute to set the alignment mode of text.
```ts
Text('Left aligned')
.width(300)
.textAlign(TextAlign.Start)
.border({ width: 1 })
.padding(10)
Text ('Center aligned')
.width(300)
.textAlign(TextAlign.Center)
.border({ width: 1 })
.padding(10)
Text('Right aligned')
.width(300)
.textAlign(TextAlign.End)
.border({ width: 1 })
.padding(10)
```
![en-us_image_0000001511421260](figures/en-us_image_0000001511421260.png)
- Use the **textOverflow** attribute to set the display mode for when the text is too long. This attribute must be used together with **maxLines**. By default, the text is automatically folded.
```ts
Text('This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content. This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content.')
.width(250)
.textOverflow({ overflow: TextOverflow.None })
.maxLines(1)
.fontSize(12)
.border({ width: 1 }).padding(10)
Text('I am extra long text, with an ellipse displayed for any excess.')
.width(250)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.fontSize(12)
.border({ width: 1 }).padding(10)
```
![en-us_image_0000001563060693](figures/en-us_image_0000001563060693.png)
![en-us_image_0000001563060701](figures/en-us_image_0000001563060701.png)
- Use the **lineHeight** attribute to set the text line height.
```ts
Text('This is the text with the line height set. This is the text with the line height set.')
.width(300).fontSize(12).border({ width: 1 }).padding(10)
Text('This is the text with the line height set. This is the text with the line height set.')
.width(300).fontSize(12).border({ width: 1 }).padding(10)
.lineHeight(20)
```
![en-us_image_0000001511740480](figures/en-us_image_0000001511740480.png)
- Use the **decoration** attribute to set the style and color of the text decorative line.
```ts
Text('This is the text')
.decoration({
type: TextDecorationType.LineThrough,
color: Color.Red
})
.borderWidth(1).padding(10).margin(5)
Text('This is the text')
.decoration({
type: TextDecorationType.Overline,
color: Color.Red
})
.borderWidth(1).padding(10).margin(5)
Text('This is the text')
.decoration({
type: TextDecorationType.Underline,
color: Color.Red
})
.borderWidth(1).padding(10).margin(5)
```
![en-us_image_0000001511580888](figures/en-us_image_0000001511580888.png)
- Use the **baselineOffset** attribute to set the baseline offset of the text.
```ts
Text('This is the text content with baselineOffset 0.')
.baselineOffset(0)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
Text('This is the text content with baselineOffset 30.')
.baselineOffset(30)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
Text('This is the text content with baselineOffset -20.')
.baselineOffset(-20)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
```
![en-us_image_0000001562820789](figures/en-us_image_0000001562820789.png)
- Use the **letterSpacing** attribute to set the letter spacing.
```ts
Text('This is the text content with letterSpacing 0.')
.letterSpacing(0)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
Text('This is the text content with letterSpacing 3.')
.letterSpacing(3)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
Text('This is the text content with letterSpacing -1.')
.letterSpacing(-1)
.fontSize(12)
.border({ width: 1 })
.padding(10)
.width('100%')
.margin(5)
```
![en-us_image_0000001562940513](figures/en-us_image_0000001562940513.png)
- Use the **minFontSize** and **maxFontSize** attributes to set the minimum and maximum font size, respectively. For the settings to take effect, these attributes must be used together with **maxLines** or layout constraint settings.
```ts
Text('My maximum font size is 30, minimum font size is 5, width is 250, and maximum number of lines is 1')
.width(250)
.maxLines(1)
.maxFontSize(30)
.minFontSize(5)
.border({ width: 1 })
.padding(10)
.margin(5)
Text('My maximum font size is 30, minimum font size is 5, width is 250, and maximum number of lines is 2')
.width(250)
.maxLines(2)
.maxFontSize(30)
.minFontSize(5)
.border({ width: 1 })
.padding(10)
.margin(5)
Text('My maximum font size is 30, minimum font size is 15, width is 250, and line height is 50')
.width(250)
.height(50)
.maxFontSize(30)
.minFontSize(15)
.border({ width: 1 })
.padding(10)
.margin(5)
Text('My maximum font size is 30, minimum font size is 15, width is 250, and line height is 100')
.width(250)
.height(100)
.maxFontSize(30)
.minFontSize(15)
.border({ width: 1 })
.padding(10)
.margin(5)
```
![en-us_image_0000001511740472](figures/en-us_image_0000001511740472.png)
- Use the **textCase** attribute to set the text case.
```ts
Text('This is the text content with textCase set to Normal.')
.textCase(TextCase.Normal)
.padding(10)
.border({ width: 1 })
.padding(10)
.margin(5)
// The text is displayed in lowercase.
Text('This is the text content with textCase set to LowerCase.')
.textCase(TextCase.LowerCase)
.border({ width: 1 })
.padding(10)
.margin(5)
// The text is displayed in uppercase.
Text('This is the text content with textCase set to UpperCase.')
.textCase(TextCase.UpperCase)
.border({ width: 1 })
.padding(10)
.margin(5)
```
![en-us_image_0000001562940529](figures/en-us_image_0000001562940529.png)
- Use the **copyOption** attribute to set whether copy and paste is allowed.
```ts
Text("This text is copyable")
.fontSize(30)
.copyOption(CopyOptions.InApp)
```
![en-us_image_0000001511580868](figures/en-us_image_0000001511580868.png)
## Adding Events
The **\<Text>** component supports the [universal events](../reference/arkui-ts/ts-universal-events-click.md). It can be bound to the **onClick**, **onTouch**, or other events to respond to user operations.
```ts
Text ('Click Me')
.onClick(()=>{
console.info('I am the response to the click event');
})
```
## Example Scenario
```ts
// xxx.ets
@Entry
@Component
struct TextExample {
build() {
Column() {
Row() {
Text("1").fontSize(14).fontColor(Color.Red).margin({ left: 10, right: 10 })
Text("I am entry 1")
.fontSize(12)
.fontColor(Color.Blue)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontWeight(300)
Text ("Top Hit")
.margin({ left: 6 })
.textAlign(TextAlign.Center)
.fontSize(10)
.fontColor(Color.White)
.fontWeight(600)
.backgroundColor(0x770100)
.borderRadius(5)
.width(15)
.height(14)
}.width('100%').margin(5)
Row() {
Text("2").fontSize(14).fontColor(Color.Red).margin({ left: 10, right: 10 })
Text("I am entry 2")
.fontSize(12)
.fontColor(Color.Blue)
.fontWeight(300)
.constraintSize({ maxWidth: 200 })
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text ("Hot")
.margin({ left: 6 })
.textAlign(TextAlign.Center)
.fontSize(10)
.fontColor(Color.White)
.fontWeight(600)
.backgroundColor(0xCC5500)
.borderRadius(5)
.width(15)
.height(14)
}.width('100%').margin(5)
Row() {
Text("3").fontSize(14).fontColor(Color.Orange).margin({ left: 10, right: 10 })
Text("I am entry 3")
.fontSize(12)
.fontColor(Color.Blue)
.fontWeight(300)
.maxLines(1)
.constraintSize({ maxWidth: 200 })
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text ("Hot")
.margin({ left: 6 })
.textAlign(TextAlign.Center)
.fontSize(10)
.fontColor(Color.White)
.fontWeight(600)
.backgroundColor(0xCC5500)
.borderRadius(5)
.width(15)
.height(14)
}.width('100%').margin(5)
Row() {
Text("4").fontSize(14).fontColor(Color.Grey).margin({ left: 10, right: 10 })
Text("I am entry 4")
.fontSize(12)
.fontColor(Color.Blue)
.fontWeight(300)
.constraintSize({ maxWidth: 200 })
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}.width('100%').margin(5)
}.width('100%')
}
}
```
![en-us_image_0000001562820805](figures/en-us_image_0000001562820805.png)
# Text Input
The **\<TextInput>** and **\<TextArea>** components are input components typically used to accept input from the user, such as comments, chat messages, and table content. They can be used in combination with other components to meet more diversified purposes, for example, login and registration. For details, see [TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) and [TextArea](../reference/arkui-ts/ts-basic-components-textarea.md).
## Creating a Text Box
The **\<TextInput>** component provides single-line text input, while the **\<TextArea>** component provides multi-line text input. To create these components, use the following APIs:
```ts
TextArea(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextAreaController})
```
```ts
TextInput(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextInputController})
```
- Single-line text box
```ts
TextInput()
```
![en-us_image_0000001511580844](figures/en-us_image_0000001511580844.png)
- Multi-line text box
```ts
TextArea()
```
![en-us_image_0000001562940481](figures/en-us_image_0000001562940481.png)
The **\<TextArea>** component automatically wraps text so that each line does not have more than the width of the component.
```ts
TextArea({text:"I am TextArea I am TextArea I am TextArea"}).width(300)
```
![en-us_image_0000001511580836](figures/en-us_image_0000001511580836.png)
## Setting the Input Box Type
The **\<TextInput>** component comes in five types. You can specify its type by setting the **type** parameter to any of the following: **Normal**, **Password**, **Email**, **Number**, and **PhoneNumber**.
- Normal type (default type)
```ts
TextInput()
.type(InputType.Normal)
```
![en-us_image_0000001562820765](figures/en-us_image_0000001562820765.png)
- Password type
```ts
TextInput()
.type(InputType.Password)
```
![en-us_image_0000001511580840](figures/en-us_image_0000001511580840.png)
## Setting Styles
- Set the placeholder text displayed when there is no input.
TextInput({placeholder:'I am placeholder text'})
```ts
TextInput({placeholder:'I am placeholder text'})
```
![en-us_image_0000001511900400](figures/en-us_image_0000001511900400.png)
- Set the current text input.
```ts
TextInput({placeholder:'I am placeholder text',text:'I am current text input'})
```
![en-us_image_0000001562820761](figures/en-us_image_0000001562820761.png)
- Use **backgroundColor** to set the background color of the text box.
```ts
TextInput({placeholder:'I am placeholder text',text:'I am current text input'})
.backgroundColor(Color.Pink)
```
![en-us_image_0000001511740444](figures/en-us_image_0000001511740444.png)
More styles can be implemented by leveraging the [universal attributes](../reference/arkui-ts/ts-universal-attributes-size.md).
## Adding Events
You can add the **onChange** event for the text box to obtain its content changes. You can also add the universal events to implement user interactions.
```ts
TextInput()
.onChange((value: string) => {
console.info(value);
})
.onFocus(() => {
console.info ('Get Focus');
})
```
## Example Scenario
In this example, the text box is used to submit forms on the user login or registration page.
```ts
@Entry
@Component
struct TextInputSample {
build() {
Column() {
TextInput({ placeholder: 'input your username' }).margin({ top: 20 })
.onSubmit((EnterKeyType)=>{
console.info(EnterKeyType+'Enter key type')
})
TextInput({ placeholder: 'input your password' }).type(InputType.Password).margin({ top: 20 })
.onSubmit((EnterKeyType)=>{
console.info(EnterKeyType+'Enter key type')
})
Button('Sign in').width(150).margin({ top: 20 })
}.padding(20)
}
}
```
![en-us_image_0000001563060653](figures/en-us_image_0000001563060653.png)
# Video Playback
The **\<Video>** component is used to play a video and control its playback. It is usually used in video players and video list pages within applications. A video automatically plays once fully loaded. When the user clicks the video area, the video is paused and the playback progress bar is displayed. The user can drag the progress bar to the desired position. For details, see [Video](../reference/arkui-ts/ts-media-components-video.md).
## Creating a \<Video> Component
You can create a **\<Video>** component by calling the following API:
```ts
Video(value: {src?: string | Resource, currentProgressRate?: number | string | PlaybackSpeed, previewUri?: string | PixelMap | Resource, controller?: VideoController})
```
Creates a **\<Video>** component. In this API, **src** indicates the path of the video source, **currentProgressRate** indicates the video playback speed, **previewUri** indicates the path of the preview image, and **controller** indicates the video controller . For details about how to load a video, see [Loading Video](#loading-video).
## Loading Video
The **\<Video>** component supports both local and online videos.
### Loading a Local Video
- Common local video
To load a local video, specify the corresponding video file in the local **rawfile** directory, as shown in the following figure.
![en-us_image_0000001562700409](figures/en-us_image_0000001562700409.png)
Use **$rawfile()** to reference the video resource.
```ts
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private innerResource: Resource = $rawfile('videoTest.mp4');
build(){
Column() {
Video({
src: this.innerResource,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
```
- Video provided by a [DataAbility](../application-models/dataability-overview.md), whose path contains the **dataability://** prefix<br>Ensure that the corresponding video resource exists.
```ts
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private videosrc: string= 'dataability://device_id/com.domainname.dataability.videodata/video/10'
build(){
Column() {
Video({
src: this.videosrc,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
```
### Loading a Video in the Application Sandbox
To load a video in the application sandbox, use a string with the **file:///data/storage** prefix. Ensure that the application has the read permission to the files in the specified path.
```ts
@Component
export struct VideoPlayer {
private controller: VideoController;
private videosrc: string = 'file:///data/storage/el2/base/haps/entry/files/show.mp4'
build() {
Column() {
Video({
src: this.videosrc,
controller: this.controller
})
}
}
}
```
### Loading an Online Video
To load online videos, you must apply for the **ohos.permission.INTERNET** permission. For details about how to apply for the permission, see [Declaring Permissions](../security/accesstoken-guidelines.md). In this scenario, the **src** attribute indicates the URL of the online video.
```ts
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private videosrc: string= 'https://www.example.com/example.mp4' // Replace the URL with that of the actual video to load.
build(){
Column() {
Video({
src: this.videosrc,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
```
## Adding Attributes
Use the [attributes](../reference/arkui-ts/ts-media-components-video.md#attributes) of the **\<Video>** component to control video playback. For example, you can set whether to mute the video and whether to display the video playback control bar.
```ts
@Component
export struct VideoPlayer {
private controller: VideoController;
build() {
Column() {
Video({
controller: this.controller
})
.muted(false) // Set whether to mute the video.
.controls(false) // Set whether to display the video playback control bar.
.autoPlay(false) // Set whether to enable auto play.
.loop(false) // Set whether to repeat the video.
.objectFit(ImageFit.Contain) // Set the video scale type.
}
}
}
```
## Adding Events
The **\<Video>** component supports various callback events in addition to the universal events. For details, see [Events](../reference/arkui-ts/ts-media-components-video.md#events).
```ts
@Entry
@Component
struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private innerResource: Resource = $rawfile('videoTest.mp4');
build(){
Column() {
Video({
src: this.innerResource,
previewUri: this.previewUris,
controller: this.controller
})
.onUpdate((event) => { // Triggered when the playback progress changes.
console.info("Video update.");
})
.onPrepared((event) => { // Triggered when video preparation is complete.
console.info("Video prepared.");
})
.onError(() => { // Triggered when the video playback fails.
console.info("Video error.");
})
}
}
}
```
## Using the Video Controller
The video controller is used to control video playback. For details, see [VideoController](../reference/arkui-ts/ts-media-components-video.md#videocontroller).
- Default controller
The default controller supports four basic features: start playback, pause playback, set the video playback position, and play the video in full screen.
```ts
@Entry
@Component
struct VideoGuide {
@State videoSrc: Resource = $rawfile('videoTest.mp4')
@State previewUri: string = 'common/videoIcon.png'
@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
build() {
Row() {
Column() {
Video({
src: this.videoSrc,
previewUri: this.previewUri,
currentProgressRate: this.curRate
})
}
.width('100%')
}
.height('100%')
}
}
```
- Custom controller
To use a custom controller, disable the default controller, and then use components such as \<Button> and \<Slider> to customize the control and display. This type of controller is applicable to scenarios where customization requirements are involved.
```ts
@Entry
@Component
struct VideoGuide {
@State videoSrc: Resource = $rawfile('videoTest.mp4')
@State previewUri: string = 'common/videoIcon.png'
@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
@State isAutoPlay: boolean = false
@State showControls: boolean = true
@State sliderStartTime: string = '';
@State currentTime: number = 0;
@State durationTime: number = 0;
@State durationStringTime: string ='';
controller: VideoController = new VideoController()
build() {
Row() {
Column() {
Video({
src: this.videoSrc,
previewUri: this.previewUri,
currentProgressRate: this.curRate,
controller: this.controller
}).controls(false).autoPlay(true)
.onPrepared((event)=>{
this.durationTime = event.duration
})
.onUpdate((event)=>{
this.currentTime =event.time
})
Row() {
Text(JSON.stringify(this.currentTime) + 's')
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.onChange((value: number, mode: SliderChangeMode) => {
this.controller.setCurrentTime(value);
}).width("90%")
Text(JSON.stringify(this.durationTime) + 's')
}
.opacity(0.8)
.width("100%")
}
.width('100%')
}
.height('40%')
}
}
```
## Remarks
The **\<Video>** component has encapsulated the basic capabilities of video playback. You do not need to create video instances or set and obtain video information. Simply set the data source and basic information to play videos. To customize video playback, see [Video Playback](../media/video-playback.md).
# Keyboard and Mouse Event
Keyboard and mouse events refer to the input events of the peripheral keyboard and mouse.
## Mouse Event
The supported mouse events include the events triggered by the peripheral mouse and touchpad.
Mouse events can trigger the following callbacks.
| Name | Description |
| ---------------------------------------- | ---------------------------------------- |
| onHover(event:&nbsp;(isHover:&nbsp;boolean)&nbsp;=&gt;&nbsp;void) | Triggered when the mouse cursor enters or leaves the component.<br>**isHover**: whether the mouse cursor hovers over the component. The value **true** means that the mouse cursor enters the component, and the value **false** means that the mouse cursor leaves the component.|
| onMouse(event:&nbsp;(event?:&nbsp;MouseEvent)&nbsp;=&gt;&nbsp;void) | Triggered when the component is clicked by a mouse button or the mouse cursor moves on the component. The **event** parameter indicates the timestamp, mouse button, action, coordinates of the clicked point on the entire screen, and coordinates of the clicked point relative to the component when the event is triggered.|
When the component is bound to the **onHover** callback, you can use the [hoverEffect](../reference/arkui-ts/ts-universal-attributes-hover-effect.md) attribute to set the hover effect of the component in hover state.
**Figure 1** Mouse event data flow
![en-us_image_0000001511900504](figures/en-us_image_0000001511900504.png)
When ArkUI receives the mouse event, it checks whether the mouse event concerns pressing, lifting, or moving of the left mouse button, and then responds accordingly.
- Yes: The mouse event is first converted into a touch event in the same position, and a collision test, gesture judgment, and callback response of the touch event are performed. The collision test and callback response of the mouse event are then performed.
- No: Only the collision test and callback response of the mouse event are performed.
>**NOTE**
>
>All touch events and gesture events that can be responded to by a single finger may be operated and responded by using the left mouse button. For example, to implement page redirection invoked by clicking a button with support for finger touches and left-clicks, you just need to bind one click event (**onClick**). If you want to implement different effects for the finger touch and the left-click, you can use the **source** parameter in the **onClick** callback to determine whether the current event is triggered by a finger or a mouse.
### onHover
```ts
onHover(event: (isHover?: boolean) => void)
```
Triggered when the mouse cursor enters or leaves the component. The **isHover** parameter indicates whether the mouse cursor hovers over the component. This event does not support custom bubbling settings. By default, event bubbling occurs between parent and child components.
If this API is bound to a component, it is triggered when the mouse cursor enters the component from outside and the value of **isHover** is **true**, or when the mouse cursor leaves the component and the value of **isHover** is **false**.
>**NOTE**
>
>Event bubbling is an event propagation in the document object model (DOM) when an event is first handled by an element and then bubbles up to its parent element.
```ts
// xxx.ets
@Entry
@Component
struct MouseExample {
@State isHovered: boolean = false;
build() {
Column() {
Button(this.isHovered ? 'Hovered!' : 'Not Hover')
.width(200).height(100)
.backgroundColor(this.isHovered ? Color.Green : Color.Gray)
.onHover((isHover: boolean) => { // Use the onHover API to listen for whether the mouse cursor is hovered over the component.
this.isHovered = isHover;
})
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
```
In this example, a **\<Button component>** is created, with the initial background color of gray and the content of **Not Hover**. The component is bound to the **onHover** callback. In the callback, **this.isHovered** is set to the callback parameter **isHover**.
When the cursor moves from outside the button to inside the button, the callback is invoked, the value of **isHover** changes to **true**, the value of **isHovered** changes to **true**, the background color of the component changes to **Color.Green**, and the content changes to **Hovered!**.
When the cursor moves from inside the button to outside the button, the callback is invoked, the value of **isHover** changes to **false**, and the component restores to its initial style.
![onHover](figures/onHover.gif)
### onMouse
```ts
onMouse(event: (event?: MouseEvent) => void)
```
Triggered when a mouse event occurs. It is triggered each time an action by the mouse cursor (**MouseAction**) is detected in the component. The parameter is a [MouseEvent](../reference/arkui-ts/ts-universal-mouse-key.md) object, which indicates the mouse event that triggers the callback. This event supports custom bubbling settings. By default, event bubbling occurs between parent and child components. It is commonly used for customized mouse behavior logic processing.
You can use the **MouseEvent** object in the callback to obtain information about the triggered event, including the coordinates (**screenX**/**screenY**/**x**/**y**), button ([MouseButton](../reference/arkui-ts/ts-appendix-enums.md#mousebutton)), action ([MouseAction](../reference/arkui-ts/ts-appendix-enums.md#mouseaction)), timestamp (**timestamp**), display area of the object that triggers the event ([EventTarget](../reference/arkui-ts/ts-universal-events-click.md)), and event source ([SourceType](../reference/arkui-ts/ts-gesture-settings.md)). The **stopPropagation** callback of **MouseEvent** is used to set whether the current event blocks bubbling.
>**NOTE**
>
>**MouseButton** indicates the physical mouse button being pressed or released that triggers the mouse event. The values are **Left**, **Right**, **Middle**, **Back**, **Forward**, and **None**. **None** indicates that no button is pressed or released, which means that the event is triggered by the mouse cursor moving on the component.
```ts
// xxx.ets
@Entry
@Component
struct MouseExample {
@State isHovered: boolean = false;
@State buttonText: string = '';
@State columnText: string = '';
build() {
Column() {
Button(this.isHovered ? 'Hovered!' : 'Not Hover')
.width(200)
.height(100)
.backgroundColor(this.isHovered ? Color.Green : Color.Gray)
.onHover((isHover: boolean) => {
this.isHovered = isHover
})
.onMouse((event: MouseEvent) => { // Set the onMouse callback for the button.
this.buttonText = 'Button onMouse:\n' + '' +
'button = ' + event.button + '\n' +
'action = ' + event.action + '\n' +
'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
'screenXY=(' + event.screenX + ',' + event.screenY + ')';
})
Divider()
Text(this.buttonText).fontColor(Color.Green)
Divider()
Text(this.columnText).fontColor(Color.Red)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.borderWidth(2)
.borderColor(Color.Red)
.onMouse((event: MouseEvent) => { // Set the onMouse callback for the column.
this.columnText = 'Column onMouse:\n' + '' +
'button = ' + event.button + '\n' +
'action = ' + event.action + '\n' +
'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
'screenXY=(' + event.screenX + ',' + event.screenY + ')';
})
}
}
```
Bind the **onMouse** API to the button based on the **onHover** example. In the callback, the values of the callback parameters, such as **button** and **action**, are displayed. The same settings are performed on the outer **\<Column>** container. The entire process can be divided into the following two actions:
1. Moving the mouse cursor: When the mouse cursor is moved from outside the button to inside the button, only the **onMouse** callback of the **\<Column>** is triggered. When the mouse cursor is moved to the button, as the **onMouse** event bubbles up by default, both the **onMouse** callbacks of the **\<Column>** and **\<Button>** components are invoked. In this process, the mouse cursor moves, but no mouse button is clicked. Therefore, in the displayed information, the value of **button** is 0 (enumerated value of **MouseButton.None**) and the value of **action** is **3** (enumerated value of **MouseAction.Move**).
2. Clicking the mouse button: After the mouse cursor enters the **\<Button>** component, the **\<Button>** component is clicked twice, namely, left-click and right-click.
Left-clicked: button = 1 (enumerated value of **MouseButton.Left**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**).
Right-click: button = 2 (enumerated value of **MouseButton.Right**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**)
![onMouse1](figures/onMouse1.gif)
To prevent the mouse event from bubbling, call the **stopPropagation()** API.
```ts
Button(this.isHovered ? 'Hovered!' : 'Not Hover')
.width(200)
.height(100)
.backgroundColor(this.isHovered ? Color.Green : Color.Gray)
.onHover((isHover: boolean) => {
this.isHovered = isHover;
})
.onMouse((event: MouseEvent) => {
event.stopPropagation(); // Prevent the mouse event from bubbling.
this.buttonText = 'Button onMouse:\n' + '' +
'button = ' + event.button + '\n' +
'action = ' + event.action + '\n' +
'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
'screenXY=(' + event.screenX + ',' + event.screenY + ')';
})
```
To prevent the mouse event of the child component (**\<Button>**) from bubbling up to its parent component (**\<Column>**), use the **event** parameter in the **onMouse** callback of **\<Button>** to call the **stopPropagation** API.
```ts
event.stopPropagation()
```
With bubbling prevented, the mouse event on the **\<Button>** component will trigger the **onMouse** callback of the **\<Button>** component, but not the **onMouse** callback of the **\<Column>** component.
### hoverEffect
```ts
hoverEffect(value: HoverEffect)
```
Sets the hover effect of the component in hover state. The parameter value type is **HoverEffect**. The **Auto**, **Scale**, and **Highlight** effects are preset and do not support customization.
**Table 1** HoverEffect
| Enum| Description |
| -------------- | ---------------------------------------- |
| Auto | Default hover effect, which varies by component. |
| Scale | Scale effect. When the mouse cursor is placed over the component, the component is scaled up from 100% to 105%. When the mouse cursor is moved away, the component is scaled down from 105% to 100%.|
| Highlight | Background fade-in and fade-out effect. When the mouse cursor is placed over the component, a white layer with 5% opacity is applied to the background color of the component, resulting in a dimmed background. When the mouse cursor is moved away, the background color of the component is restored to the original style.|
| None | No effect. |
```ts
// xxx.ets
@Entry
@Component
struct HoverExample {
build() {
Column({ space: 10 }) {
Button('Auto')
.width(170).height(70)
Button('Scale')
.width(170).height(70)
.hoverEffect(HoverEffect.Scale)
Button('Highlight')
.width(170).height(70)
.hoverEffect(HoverEffect.Highlight)
Button('None')
.width(170).height(70)
.hoverEffect(HoverEffect.None)
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
```
![hoverEffect](figures/hoverEffect.gif)
For the **\<Button>** component, **Auto** creates the same effect as **Scale**.
## Key Event
**Figure 2** Key event data flow
![en-us_image_0000001511580944](figures/en-us_image_0000001511580944.png)
The key event is triggered by a device such as a peripheral keyboard, and is sent to the currently focused window after being converted by the driver and multi-mode processing. After obtaining the event, the window distributes the event to the input method (which consumes the key as the input). If the input method does not consume the key event, the window sends the event to the ArkUI framework. Therefore, when an input box component has focus and an input method is enabled, most key events are consumed by the input method. For example, a letter key is used by the input method to enter a letter in the input box, and an arrow key is used by the input method to switch to the desired candidate word.
After the key event is sent to the ArkUI framework, it first identifies the complete focus chain, and then sends the key event one by one from the leaf node to the root node.
### onKeyEvent
```ts
onKeyEvent(event: (event?: KeyEvent) => void)
```
Triggered when the bound component has [focus](arkts-common-events-focus-event.md) and a key event occurs on the component. The callback parameter [KeyEvent](../reference/arkui-ts/ts-universal-events-key.md) can be used to obtain the information about the key event, including [KeyType](../reference/arkui-ts/ts-appendix-enums.md#keytype), [keyCode](../reference/apis/js-apis-keycode.md), keyText, [KeySource](../reference/arkui-ts/ts-appendix-enums.md#keysource), **deviceId**, **metaKey**, **timestamp**, and **stopPropagation**.
```ts
// xxx.ets
@Entry
@Component
struct KeyEventExample {
@State buttonText: string = '';
@State buttonType: string = '';
@State columnText: string = '';
@State columnType: string = '';
build() {
Column() {
Button('onKeyEvent')
.width(140).height(70)
.onKeyEvent((event: KeyEvent) => {// Set the onKeyEvent event for the <Button> component.
if (event.type === KeyType.Down) {
this.buttonType = 'Down';
}
if (event.type === KeyType.Up) {
this.buttonType = 'Up';
}
this.buttonText = 'Button: \n' +
'KeyType:' + this.buttonType + '\n' +
'KeyCode:' + event.keyCode + '\n' +
'KeyText:' + event.keyText;
})
Divider()
Text(this.buttonText).fontColor(Color.Green)
Divider()
Text(this.columnText).fontColor(Color.Red)
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
.onKeyEvent((event: KeyEvent) => {// Set the onKeyEvent event for the parent container <Column>.
if (event.type === KeyType.Down) {
this.columnType = 'Down';
}
if (event.type === KeyType.Up) {
this.columnType = 'Up';
}
this.columnText = 'Column: \n' +
'KeyType:' + this.buttonType + '\n' +
'KeyCode:' + event.keyCode + '\n' +
'KeyText:' + event.keyText;
})
}
}
```
In the preceding example, **onKeyEvent** is bound to the **\<Button>** component and its parent container **\<Column>**. After the application opens and loads a page, the first focusable non-container component in the component tree automatically obtains focus. As the application has only one **\<Button>** component, the component automatically obtains focus. Because the **\<Button>** component is a child node of the **\<Column>** component, the **\<Column>** component also obtains focus. For details about the focus obtaining mechanism, see [Focus Event](arkts-common-events-focus-event.md).
![en-us_image_0000001511421324](figures/en-us_image_0000001511421324.gif)
After the application is opened, press the following keys in sequence: Space, Enter, Left Ctrl, Left Shift, Letter A, and Letter Z.
1. Because the **onKeyEvent** event bubbles by default, the **onKeyEvent** callbacks of both **\<Button>** and **\<Column>** are invoked.
2. Each key has two callbacks, which correspond to **KeyType.Down** and **KeyType.Up** respectively, indicating that the key is pressed and then lifted.
To prevent the key event of the **\<Button>** component from bubbling up to its parent container **\<Column>**, add the **event.stopPropagation()** API to the **onKeyEvent** callback of **\<Button>**.
```ts
Button('onKeyEvent')
.width(140).height(70)
.onKeyEvent((event: KeyEvent) => {
// Use stopPropagation to prevent the key event from bubbling up.
event.stopPropagation();
if (event.type === KeyType.Down) {
this.buttonType = 'Down';
}
if (event.type === KeyType.Up) {
this.buttonType = 'Up';
}
this.buttonText = 'Button: \n' +
'KeyType:' + this.buttonType + '\n' +
'KeyCode:' + event.keyCode + '\n' +
'KeyText:' + event.keyText;
})
```
![en-us_image_0000001511900508](figures/en-us_image_0000001511900508.gif)
# Touchscreen Event
Touchscreen events are events triggered when a finger or stylus is placed on, moved along, or lifted from a component. They can be classified as [click event](#click-event), [drag event](#drag-event), or [touch event](#touch-event).
**Figure 1** Touchscreen event principles
![en-us_image_0000001562700461](figures/en-us_image_0000001562700461.png)
## Click Event
A click event is triggered when a complete press and lift action performed by using a finger or a stylus. When a click event occurs, the following callback is triggered:
```ts
onClick(event: (event?: ClickEvent) => void)
```
The **event** parameter provides the coordinates of the click relative to the window or component as well as the event source where the click occurs, for example, a button, a click on which shows or hides an image.
```ts
@Entry
@Component
struct IfElseTransition {
@State flag: boolean = true;
@State btnMsg: string = 'show';
build() {
Column() {
Button(this.btnMsg).width(80).height(30).margin(30)
.onClick(() => {
if (this.flag) {
this.btnMsg = 'hide';
} else {
this.btnMsg = 'show';
}
// Click the button to show or hide the image.
this.flag = !this.flag;
})
if (this.flag) {
Image($r('app.media.icon')).width(200).height(200)
}
}.height('100%').width('100%')
}
}
```
## Drag Event
A drag event is triggered when a user long presses a component (&gt;=500 ms) using a finger or stylus and drags the component to the drop target. The following figure illustrates the process of triggering a drag event.
![en-us_image_0000001562820825](figures/en-us_image_0000001562820825.png)
Whether a drag event can be triggered depends on the distance of long-pressing and dragging with the finger or stylus on the screen. The drag event is triggered when this distance reaches 5 vp. ArkUI supports intra-application and cross-application drag events.
The drag event provides the following [APIs](../reference/arkui-ts/ts-universal-events-drag-drop.md).
| API | Description |
| ---------------------------------------- | ---------------------------------------- |
| onDragStart(event: (event?: DragEvent, extraParams?: string) =&gt; CustomBuilder \| DragItemInfo) | Triggered when dragging starts. Currently, only custom **pixelmap** objects and custom components are supported. |
| onDragEnter(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item enters a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDragLeave(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item leaves a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDragMove(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item moves in a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
| onDrop(event: (event?: DragEvent, extraParams?: string) =&gt; void) | Triggered when the dragged item is dropped on a valid drop target.<br/>**DragEvent**: position where the drag occurs.<br>**extraParmas**: custom information about the drag event. |
The following is an example of dragging a component out of a window in cross-window dragging:
```ts
import image from '@ohos.multimedia.image';
@Entry
@Component
struct Index {
@State visible: Visibility = Visibility.Visible
private pixelMapReader = undefined
aboutToAppear() {
console.info('begin to create pixmap has info message: ')
this.createPixelMap()
}
createPixelMap() {
let color = new ArrayBuffer(4 * 96 * 96);
var buffer = new Uint8Array(color);
for (var i = 0; i < buffer.length; i++) {
buffer[i] = (i + 1) % 255;
}
let opts = {
alphaType: 0,
editable: true,
pixelFormat: 4,
scaleMode: 1,
size: { height: 96, width: 96 }
}
const promise = image.createPixelMap(color, opts);
promise.then((data) => {
console.info('create pixmap has info message: ' + JSON.stringify(data))
this.pixelMapReader = data;
})
}
@Builder pixelMapBuilder() {
Text('drag item')
.width('100%')
.height(100)
.fontSize(16)
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(0xFFFFFF)
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('App1')
.width('40%')
.height(80)
.fontSize(20)
.margin(30)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.visibility(Visibility.Visible)
Text('Across Window Drag This')
.width('80%')
.height(80)
.fontSize(16)
.margin(30)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.visibility(this.visible)
.onDragStart(() => { // Triggered when cross-window dragging starts.
console.info('Text onDrag start')
return { pixelMap: this.pixelMapReader, extraInfo: 'custom extra info.' }
})
.onDrop((event: DragEvent, extraParams: string) => {
console.info('Text onDragDrop, ')
this.visible = Visibility.None // Make the source invisible after the dragging is complete.
})
}
.width('100%')
.height('100%')
}
}
```
The following is an example of dragging a component into a window in cross-window dragging:
```ts
@Entry
@Component
struct Index {
@State number: string[] = ['drag here']
@State text: string = ''
@State bool1: boolean = false
@State bool2: boolean = false
@State visible: Visibility = Visibility.Visible
@State visible2: Visibility = Visibility.None
scroller: Scroller = new Scroller()
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('App2')
.width('40%')
.height(80)
.fontSize(20)
.margin(30)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.visibility(Visibility.Visible)
List({ space: 20, initialIndex: 0 }) {
ForEach(this.number, (item) => {
ListItem() {
Text('' + item)
.width('100%')
.height(80)
.fontSize(16)
.borderRadius(10)
.textAlign(TextAlign.Center)
.backgroundColor(0xFFFFFF)
}
}, item => item)
ListItem() {
Text('Across Window Drag This')
.width('80%')
.height(80)
.fontSize(16)
.margin(30)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.visibility(this.visible2)
}
}
.height('50%')
.width('90%')
.border({ width: 1 })
.divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 })
.onDragEnter((event: DragEvent, extraParams: string) => { // Drag the component into the window.
console.info('List onDragEnter, ' + extraParams)
})
.onDragMove((event: DragEvent, extraParams: string) => { // Move the component during dragging.
console.info('List onDragMove, ' + extraParams)
})
.onDragLeave((event: DragEvent, extraParams: string) => { // Drag the component out of the window.
console.info('List onDragLeave, ' + extraParams)
})
.onDrop((event: DragEvent, extraParams: string) => { // Release the component.
console.info('List onDragDrop, ' + extraParams)
this.visible2 = Visibility.Visible // Make the dragged object visible.
})
}
.width('100%')
.height('100%')
}
}
```
## Touch Event
A touch event is triggered when a finger or stylus is placed on, moved along, or lifted from a component.
```ts
onTouch(event: (event?: TouchEvent) => void)
```
- If **event.type** is **TouchType.Down**, the finger or stylus is placed on the component.
- If **event.type** is **TouchType.Up**, the finger or stylus is lifted from the component.
- If **event.type** is **TouchType.Move**, the finger or stylus is moved along the component.
The touch event supports single and multi-touch interactions. Information about the touch event can be obtained using the **event** parameter, such as the location of the finger that triggers the event, unique identifier of the finger, finger information changed, and the input device source.
```ts
// xxx.ets
@Entry
@Component
struct TouchExample {
@State text: string = '';
@State eventType: string = '';
build() {
Column() {
Button('Touch').height(40).width(100)
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.eventType = 'Down';
}
if (event.type === TouchType.Up) {
this.eventType = 'Up';
}
if (event.type === TouchType.Move) {
this.eventType = 'Move';
}
this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: '
+ event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:('
+ event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:'
+ event.target.area.width + '\nheight:' + event.target.area.height
})
Button('Touch').height(50).width(200).margin(20)
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.eventType = 'Down';
}
if (event.type === TouchType.Up) {
this.eventType = 'Up';
}
if (event.type === TouchType.Move) {
this.eventType = 'Move';
}
this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: '
+ event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:('
+ event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:'
+ event.target.area.width + '\nheight:' + event.target.area.height
})
Text(this.text)
}.width('100%').padding(30)
}
}
```
![en-us_image_0000001511900468](figures/en-us_image_0000001511900468.gif)
# Event Overview
Interaction events are classified into touchscreen events, keyboard and mouse events, and focus events based on trigger types.
- [Touchscreen event](arkts-common-events-touch-screen-event.md): single-finger or single-stroke operation performed by a finger or stylus on the touchscreen.
- [Keyboard and mouse event](arkts-common-events-device-input-event.md): includes operation events of the peripheral mouse or touchpad and key events of the peripheral keyboard.
- The mouse event refers to an event responded to when an operation is performed with a peripheral mouse/touchpad.
- The key event refer to an event responded to when an operation is performed with a peripheral keyboard.
- [Focus event](arkts-common-events-focus-event.md): controls the focusability and response events of the component in the preceding ways.
The gesture event includes the gesture binding method and the bound gesture. The bound gesture may be classified into two types: a single gesture and a combined gesture, and is distinguished according to complexity of the gesture.
- [Gesture binding](arkts-gesture-events-binding.md): binds a single gesture or a combination of gestures to a component and declares the response priority of the bound gesture.
- [Single gesture](arkts-gesture-events-single-gesture.md): basic unit of a gesture, which is a part of all complex gestures.
- [Combined gesture](arkts-gesture-events-combined-gestures.md): a combination of multiple single gestures. Multiple single gestures can be combined into a combined gesture according to a declared type and a certain rule, and the combined gesture can be used.
# Drawing Geometric Shapes
The drawing components are used to draw graphs on the page. The **\<Shape>** component is the parent component of the drawing components. The attributes of **\<Shape>** are universal attributes supported by all the drawing components. For details, see [Shape](../reference/arkui-ts/ts-drawing-components-shape.md).
## Creating a Drawing Component
A drawing component can be created in either of the following ways:
- Create a drawing component with **\<Shape>** as their parent to implement the effect similar to SVG. The API used is as follows:
```ts
Shape(value?: PixelMap)
```
In the API, the **value** parameter sets the drawing target. You can draw a graph in the specified **PixelMap** object. If the **value** parameter is not set, the graph is drawn in the current drawing target.
```ts
Shape() {
Rect().width(300).height(50)
}
```
- Create an independent drawing component to draw a specific shape. Seven shapes are supported: [Circle](../reference/arkui-ts/ts-drawing-components-circle.md), [Ellipse](../reference/arkui-ts/ts-drawing-components-ellipse.md), [Line](../reference/arkui-ts/ts-drawing-components-line.md), [Polyine](../reference/arkui-ts/ts-drawing-components-polyline.md), [Polygon](../reference/arkui-ts/ts-drawing-components-polygon.md), [Path](../reference/arkui-ts/ts-drawing-components-path.md), and [Rect](../reference/arkui-ts/ts-drawing-components-rect.md). The following uses the **Circle** API as an example:
```ts
Circle(options?: {width?: string | number, height?: string | number}
```
This API draws a circle on a page. The **width** parameter indicates the width of the circle, and the **height** parameter indicates the height of the circle. The diameter of the circle is determined by the minimum width and height.
```ts
Circle({ width: 150, height: 150 })
```
![creation-2](figures/creation-2.jpg)
## Viewport
```ts
viewPort{ x?: number | string, y?: number | string, width?: number | string, height?: number | string }
```
Creates a viewport, which is a rectangle in the user space that maps to the view boundary established for the associated SVG element. The value of the **viewport** attribute contains four optional parameters: **x**, **y**, **width**, and **height**. **x** and **y** indicate the coordinates of the upper left corner of the viewport, and **width** and **height** indicate the size of the viewport.
The following three examples describe how to use the viewport:
- Zoom in or zoom out a graph through the shape viewport.
```ts
// Draw a circle whose width and height are both 150.
Text ('Original Size Circle')
Circle({width: 75, height: 75}).fill('#E87361')
Row({space:10}) {
Column() {
// Create a shape component whose width and height are both 150, the background color is yellow, and a viewport whose width and height are both 75. Fill the viewport with a blue rectangle and draw a circle with a diameter of 75 in the viewport.
// The drawing is complete. The viewport is zoomed in twice based on the width and height of the component.
Text ('Enlarged Circle')
Shape() {
Rect().width('100%').height('100%').fill('#0097D4')
Circle({width: 75, height: 75}).fill('#E87361')
}
.viewPort({x: 0, y: 0, width: 75, height: 75})
.width(150)
.height(150)
.backgroundColor('#F5DC62')
}
Column() {
// Create a shape component whose width and height are both 150, the background color is yellow, and a viewport whose width and height are both 300. Fill the viewport with a green rectangle and draw a circle with a diameter of 75 in the viewport.
// After the drawing is complete, the viewport is zoomed out by twice based on the width and height of the component.
Text ('Shrunk Circle')
Shape() {
Rect().width('100%').height('100%').fill('#BDDB69')
Circle({width: 75, height: 75}).fill('#E87361')
}
.viewPort({x: 0, y: 0, width: 300, height: 300})
.width(150)
.height(150)
.backgroundColor('#F5DC62')
}
}
```
![2023032401632](figures/2023032401632.jpg)
- Create a shape component whose width and height are both 300, with a yellow background and a viewport whose width and height are both 300. Fill the viewport with a blue rectangle and draw a circle with a radius of 75 in the viewport.
```ts
Shape() {
Rect().width("100%").height("100%").fill("#0097D4")
Circle({ width: 150, height: 150 }).fill("#E87361")
}
.viewPort({ x: 0, y: 0, width: 300, height: 300 })
.width(300)
.height(300)
.backgroundColor("#F5DC62")
```
![viewport-2](figures/viewport-2.jpg)
- Create a shape component whose width and height are both 300, with a yellow background and a viewport whose width and height are both 300. Fill the viewport with a blue rectangle, draw a circle with a radius of 75 in the viewport, and move the viewport 150 to the right and below respectively.
```ts
Shape() {
Rect().width("100%").height("100%").fill("#0097D4")
Circle({ width: 150, height: 150 }).fill("#E87361")
}
.viewPort({ x: -150, y: -150, width: 300, height: 300 })
.width(300)
.height(300)
.backgroundColor("#F5DC62")
```
![viewport-3](figures/viewport-3.jpg)
## Setting Styles
The drawing component allows you to change the component style through various attributes.
- You can use **fill** to set the color of the filling area of the component.
```ts
Path()
.width(100)
.height(100)
.commands('M150 0 L300 300 L0 300 Z')
.fill("#E87361")
```
![2023022792216(1)](figures/2023022792216(1).jpg)
- You can use **stroke** to set the stroke color of a component.
```ts
Path()
.width(100)
.height(100)
.fillOpacity(0)
.commands('M150 0 L300 300 L0 300 Z')
.stroke(Color.Red)
```
![stroke](figures/stroke.jpg)
- You can use **strokeOpacity** to set the stroke opacity.
```ts
Path()
.width(100)
.height(100)
.fillOpacity(0)
.commands('M150 0 L300 300 L0 300 Z')
.stroke(Color.Red)
.strokeWidth(10)
.strokeOpacity(0.2)
```
![strokeopacity](figures/strokeopacity.jpg)
- You can use **strokeLineJoin** to set the join style of the stroke. Options include **Bevel**, **Miter**, and **Round**.
```ts
Polyline()
.width(100)
.height(100)
.fillOpacity(0)
.stroke(Color.Red)
.strokeWidth(8)
.points([[20, 0], [0, 100], [100, 90]])
// Set the join style of the stroke to Round.
.strokeLineJoin(LineJoinStyle.Round)
```
![strokeLineJoin](figures/strokeLineJoin.jpg)
- **strokeMiterLimit** places a limit on the ratio of the miter length to the value of **strokeWidth** used to draw a miter join.
The miter length indicates the distance from the outer tip to the inner corner of the miter. This attribute must be set to a value greater than or equal to 1 and takes effect when **strokeLineJoin** is set to **LineJoinStyle.Miter**.
```ts
Polyline()
.width(100)
.height(100)
.fillOpacity(0)
.stroke(Color.Red)
.strokeWidth(10)
.points([[20, 0], [20, 100], [100, 100]])
// Set the join style of the stroke to Miter.
.strokeLineJoin(LineJoinStyle.Miter)
// Set the limit on the ratio of the miter length to the value of strokeWidth used to draw a miter join.
.strokeMiterLimit(1/Math.sin(45))
Polyline()
.width(100)
.height(100)
.fillOpacity(0)
.stroke(Color.Red)
.strokeWidth(10)
.points([[20, 0], [20, 100], [100, 100]])
.strokeLineJoin(LineJoinStyle.Miter)
.strokeMiterLimit(1.42)
```
![2023032405917](figures/2023032405917.jpg)
- Use the **antiAlias** attribute to set whether to enable anti-aliasing. The default value is true, indicating that anti-aliasing is enabled.
```ts
// Enable anti-aliasing.
Circle()
.width(150)
.height(200)
.fillOpacity(0)
.strokeWidth(5)
.stroke(Color.Black)
```
![untitled](figures/untitled.png)
```ts
// Disable anti-aliasing.
Circle()
.width(150)
.height(200)
.fillOpacity(0)
.strokeWidth(5)
.stroke(Color.Black)
.antiAlias(false)
```
![2023032411518](figures/2023032411518.jpg)
## Example Scenario
- Draw a closed path at (-80, -5). The fill color is 0x317AF7, the stroke width is 10, the stroke color is red, and the Join style of the stroke is miter (default value).
```ts
@Entry
@Component
struct ShapeExample {
build() {
Column({ space: 10 }) {
Shape() {
Path().width(200).height(60).commands('M0 0 L400 0 L400 150 Z')
}
.viewPort({ x: -80, y: -5, width: 500, height: 300 })
.fill(0x317AF7)
.stroke(Color.Red)
.strokeWidth(3)
.strokeLineJoin(LineJoinStyle.Miter)
.strokeMiterLimit(5)
}.width('100%').margin({ top: 15 })
}
}
```
![scenario-1](figures/scenario-1.jpg)
- Draw a circle with a diameter of 150 mm and a ring with a diameter of 150 mm and a red dotted line (use the shorter side as the diameter if the width and height are different).
```ts
@Entry
@Component
struct CircleExample {
build() {
Column({ space: 10 }) {
// Draw a circle whose diameter is 150.
Circle({ width: 150, height: 150 })
// Draw a ring with a diameter of 150 mm and a red dotted line.
Circle()
.width(150)
.height(200)
.fillOpacity(0)
.strokeWidth(3)
.stroke(Color.Red)
.strokeDashArray([1, 2])
}.width('100%')
}
}
```
![scenario-2](figures/scenario-2.jpg)
# Gesture Binding
You can bind to each component different gesture events and design the logic for responding to these events. When a gesture is successfully recognized, the ArkUI framework notifies the component of the gesture recognition result through event callback.
## gesture (Common Gesture Binding Method)
```ts
.gesture(gesture: GestureType, mask?: GestureMask)
```
**gesture** is a frequently used API for binding a gesture to a component.
For example, you can use it to bind the tap gesture to the **\<Text>** component.
```ts
// xxx.ets
@Entry
@Component
struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
// Use the gesture API to bind the tap gesture.
.gesture(
TapGesture()
.onAction(() => {
console.info('TapGesture is onAction');
}))
}
.height(200)
.width(250)
}
}
```
## priorityGesture (Gesture Binding Method with Priority)
```ts
.priorityGesture(gesture: GestureType, mask?: GestureMask)
```
The **priorityGesture** API binds gestures that are preferentially recognized to a component.
By default, the child component preferentially recognizes the gesture specified by **gesture**, and the parent component preferentially recognizes the gesture specified by **priorityGesture** (if set).
In the following example, the parent component **\<Column>** and child component **\<Text>** are both bound to the tap gesture. As the **\<Column>** is bound to the gesture through **priorityGesture**, the tap gesture recognized by the parent component is preferentially responded to.
```ts
// xxx.ets
@Entry
@Component
struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
.gesture(
TapGesture()
.onAction(() => {
console.info('Text TapGesture is onAction');
}))
}
.height(200)
.width(250)
// When the tap gesture is bound to the parent <Column> component through priorityGesture, the tap gesture event of the <Text> component is ignored when the text area is tapped, and the tap gesture event of the<Column> component is preferentially responded to.
.priorityGesture(
TapGesture()
.onAction(() => {
console.info('Column TapGesture is onAction');
}), GestureMask.IgnoreInternal)
}
}
```
## parallelGesture (Parallel Gesture Binding Method)
```ts
.parallelGesture(gesture: GestureType, mask?: GestureMask)
```
The **parallelGesture** API binds to a component the gesture that can be triggered together with the child component gesture.
By default, the gesture event does not bubble up. When a parent component and a child component are bound to a same gesture, the gesture events bound to the parent component and the child component compete with each other, and a gesture event of at most one component can be responded to. When **parallelGesture** is set, the same gesture events can be triggered for the parent and child components, thereby implementing a bubbling effect.
```ts
// xxx.ets
@Entry
@Component
struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
.gesture(
TapGesture()
.onAction(() => {
console.info('Text TapGesture is onAction');
}))
}
.height(200)
.width(250)
// When parallelGesture is set, the tap gestures on the <Column> component and on the child <Text> component are both recognized.
.parallelGesture(
TapGesture()
.onAction(() => {
console.info('Column TapGesture is onAction');
}), GestureMask.IgnoreInternal)
}
}
```
>**NOTE**
>
>When the parent component and the child component are bound to both the click gesture and the double-click gesture, both the parent component and the child component respond only to the click gesture.
# Combined Gestures
A combined gesture consists of multiple single gestures. Different GestureModes are used in GestureGroup to declare the type of the combined gesture. [Continuous recognition](#continuous-recognition), [parallel recognition](#parallel-recognition), and [exclusive recognition](#exclusive-recognition) are supported for a group of gestures.
```ts
GestureGroup(mode:GestureMode, ...gesture:GestureType[])
```
- **mode**: recognition mode of combined gestures. This parameter is mandatory and belongs to the **GestureMode** enumeration class.
- **gesture**: array consisting of multiple gestures. This parameter is mandatory. .
## Continuous Recognition
For continuous recognition, the value of **GestureMode** is **Sequence**. In this gesture mode, gestures registered in the combined gestures will be recognized according to the registration sequence until they are all recognized successfully. If any of the registered gestures fails to be recognized, all gestures fail to be recognized.
In the following example, the combined gestures for continuous recognition are the long press gesture and pan gesture.
The **translate** attribute is bound to a **\<Column>** component. You can set the attribute to translate the component. Then, bind **LongPressGesture** and **PanGesture** to the component in the **Sequence** gesture mode. When a long press gesture is recognized, the displayed number is updated. When the user drags the component after the long press gesture, the component is dragged based on the callback function of the pan gesture.
```ts
// xxx.ets
@Entry
@Component
struct Index {
@State offsetX: number = 0;
@State offsetY: number = 0;
@State count: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
@State borderStyles: BorderStyle = BorderStyle.Solid
build() {
Column() {
Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
.fontSize(28)
}
// Bind the translate attribute to translate the component.
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.height(250)
.width(300)
// The following combined gestures are recognized in sequence. When the long press gesture event is not triggered correctly, the pan gesture event is not triggered.
.gesture(
// Set the gesture mode to Sequence.
GestureGroup(GestureMode.Sequence,
// The first gesture recognized in the combined gestures is the long press gesture, which can be responded to for multiple times.
LongPressGesture({ repeat: true })
// When the long press gesture is successfully recognized, the value of count displayed on the <Text> component is increased.
.onAction((event: GestureEvent) => {
if (event.repeat) {
this.count++;
}
console.info('LongPress onAction');
})
.onActionEnd(() => {
console.info('LongPress end');
}),
// The pan gesture is triggered when the component is dragged after the long press gesture is recognized.
PanGesture()
.onActionStart(() => {
this.borderStyles = BorderStyle.Dashed;
console.info('pan start');
})
// When the gesture is triggered, the pan distance is obtained based on the callback, and the displacement distance of the component is modified. In this way, the component is translated.
.onActionUpdate((event: GestureEvent) => {
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
console.info('pan update');
})
.onActionEnd(() => {
this.positionX = this.offsetX;
this.positionY = this.offsetY;
this.borderStyles = BorderStyle.Solid;
})
)
)
}
}
```
![sequence](figures/sequence.gif)
>**NOTE**
>
>The drag event is a typical use case of continuous recognition with the long press gesture and pan gesture combined. It is triggered only when the user performs the pan gesture within the preset time frame after a long press gesture is recognized. If the long press gesture is not recognized or the pan gesture is not performed within the preset time frame, the drag event will not be triggered.
## Parallel Recognition
For parallel recognition, the value of **GestureMode** is **Parallel**. In this gesture mode, gestures registered in the combined gestures will be recognized at the same time until they are all recognized successfully. The gestures are recognized in parallel without affecting each other.
For example, if the tap gesture and the double-tap gesture are bound to the \**<Column>** component in parallel recognition mode, they can be recognized at the same time, and the recognition of these two gestures does not interfere with each other.
```ts
// xxx.ets
@Entry
@Component
struct Index {
@State count1: number = 0;
@State count2: number = 0;
build() {
Column() {
Text('parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
.fontSize(28)
}
.height(200)
.width(250)
// The following combined gestures are recognized in parallel mode. After a tap gesture is recognized successfully, if another tap gesture is recognized within the specified time frame, a double-tap gesture will also be recognized.
.gesture(
GestureGroup(GestureMode.Parallel,
TapGesture({ count: 1 })
.onAction(() => {
this.count1++;
}),
TapGesture({ count: 2 })
.onAction(() => {
this.count2++;
})
)
)
}
}
```
![parallel](figures/parallel.gif)
>**NOTE**
>
>After a tap gesture and a double-tap gesture are combined for parallel recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
>
>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
>
>When there are two taps and the interval between the two taps is within a specified period (300 ms by default), two tap events and one double-tap event are triggered.
>
>When there are two taps, but the interval between the two taps exceeds the specified time, two tap events are triggered but the double-tap event is not triggered.
## Exclusive Recognition
For exclusive recognition, the value of **GestureMode** is **Exclusive**. In this gesture mode, gestures registered in the combined gesture are recognized at the same time. If one gesture is recognized successfully, the gesture recognition ends, and all other gestures fail to be recognized.
For example, if the tap gesture and the double-tap gesture are bound to the \**<Column>** component in exclusive recognition mode, only a tap gesture event can be triggered. This is because a tap gesture requires a single tap to be triggered, and a double-tap gesture event requires two taps to be triggered; each tap event is consumed by the tap gesture and cannot be accumulated into a double-tap gesture.
```ts
// xxx.ets
@Entry
@Component
struct Index {
@State count1: number = 0;
@State count2: number = 0;
build() {
Column() {
Text('parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
.fontSize(28)
}
.height(200)
.width(250)
// The following combined gestures are mutually exclusive. After the tap gesture is recognized successfully, the double-tap gesture fails to be recognized.
.gesture(
GestureGroup(GestureMode.Exclusive,
TapGesture({ count: 1 })
.onAction(() => {
this.count1++;
}),
TapGesture({ count: 2 })
.onAction(() => {
this.count2++;
})
)
)
}
}
```
![exclusive](figures/exclusive.gif)
>**NOTE**
>
>After a tap gesture and a double-tap gesture are combined for exclusive recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
>
>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
>
>When there are two taps, the gesture recognition is declared as successful when the first tap gesture is recognized. In this case, the double-tap gesture fails to be recognized. Even if the second tap is performed within the specified time, the double-tap gesture event is not responded to. Instead, another tap gesture event is triggered.
# Layout Overview
In declarative UI, page layout is the art of organizing custom components sequentially over a page. A well-designed layout can help you present information intuitively and effectively.
You design page layout by leveraging specific components or attributes to control the size and position of components on pages. The design process involves the following steps:
- Determine the layout structure of the page.
- Analyze the elements on the page.
- Select container components and attributes to control the position and size constraints of each element on the page.
## Layout Structure
A layout is generally in a hierarchical structure, which represents the overall architecture in the UI. Below is a common page structure.
**Figure 1** Common page structure
![common-page-structure](figures/common-page-structure.png)
To achieve the preceding effect, you need to declare the corresponding elements on the page. **Page** indicates the root node of the page, and other elements such as **Column** and **Row** are built-in components. ArkUI provides a wide variety of layout components, which you can draw on to implement different layouts. For example, you can use **Row** to implement a linear layout.
## Layout Elements
You can leverage layout-related container components to create a specific layout. For example, the **List** component can form a linear layout.
**Figure 2** Layout elements
![layout-element-omposition](figures/layout-element-omposition.png)
- Component area (blue block): size of the component and is determined by the width and height attributes.
- Component content area (yellow block): size of the component area minus the paddings of the component. It is used as the layout calculation constraint for component content (or child component) size calculation.
- Component content (green block): size of the component content, for example, size of the text content. The component content may not match the component content area. For example, if fixed width and height values are set, the component content area is the size obtained with the width and height minus the paddings. The component content is the size calculated by the layout engine, which may be less than the component content area. When the component content and component content area do not match, the **align** attribute takes effect, which defines the alignment mode of the component content in the component content area, for example, center aligned.
- Component layout bounds (dotted lines): component area plus the margins (if supplied).
## Layout Selection
The declarative UI provides eight common layouts. Choose a layout that best suits the use case.
| Layout | Description |
| ---------------------------------------- | ---------------------------------------- |
| [Linear layout](arkts-layout-development-linear.md) (Row and Column)| Use this layout when there are multiple sub-elements and they can be arranged linearly. |
| [Stack layout](arkts-layout-development-stack-layout.md) (Stack)| Use this layout when you want to stack elements. The stacking does not occupy or affect the layout space of other child components in the same container. For example, when the [\<Panel>](../reference/arkui-ts/ts-container-panel.md) component is displayed as a child, superimposing it over other components makes more sense. In this case, the stack layout is preferred at the outer layer.|
| [Flex layout](arkts-layout-development-flex-layout.md) (Flex)| The flex layout is similar to the linear layout. However, it empowers the container to adjust the size of its child components to best fill the available space. Use this layout when you need elements to stretch or shrink to fit into the container.|
| [Relative layout](arkts-layout-development-relative-layout.md) (RelativeContainer)| The relative layout is a two-dimensional layout system. It does not need to comply with linear layout rules, and therefore exhibits more flexibility. By setting anchor rules (**AlignRules**) on a child component, you enable the component to position itself on the horizontal axis and vertical axis as relative to other child component in the container. Anchor rules support compression, stretching, stacking, and wrapping of child components. Use this layout when the distribution of elements is complex or when a linear layout may result in deeply nested components in the container.|
| [Responsive grid layout](arkts-layout-development-grid-layout.md) (GridRow and GridCol)| The responsive grid is an auxiliary positioning tool for a multi-device application, dividing space into rows and columns. Unlike the regular grid, the responsive grid is not allocating fixed-size space. Instead, it allows a layout to dynamically change based on the screen size. In this way, the design and development costs for adapting to different screen sizes are significantly reduced, and the overall design and development process is more orderly and rhythmic. In addition, the responsive grid offers a consistent display experience across devices. Use this layout when you are presenting the same content on different screen sizes.|
| [Media query](arkts-layout-development-media-query.md) (\@ohos.mediaquery)| You can use media queries to apply application styles based on the device type or device state. For example, you can apply specific layouts based on the attribute information of the target device and application, and update a page layout to reflect the dynamic screen changes.|
| [List](arkts-layout-development-create-list.md) (List)| Use lists to easily and efficiently display structured, scrollable information. In ArkUI, the list allows you to lay out elements in the horizontal or vertical layout and is able to adapt to the number of elements in the cross axis direction. It can scroll when the content overflows. Use this layout when you are presenting similar data types or data type sets, such as images and text.|
| [Grid](arkts-layout-development-create-grid.md) (Grid)| As an important adaptive layout, the grid excels at spacing elements evenly and defining the relationship between the elements. The grid layout controls the number of cells occupied by child components, number of rows or columns that child components span, and how the child components and spacing are adjusted proportionally when the grid container size changes. Use this layout in scenarios where space needs to be allocated evenly or based on a fixed proportion, such as calculators, albums, and calendars.|
| [Looping](arkts-layout-development-create-looping.md) (Swiper)| Use this layout when you want to implement ad rotation, image preview, or scrollable content. |
## Layout Position
Attributes such as **position** and **offset** affect the position of the layout container relative to itself or other components.
| Positioning Capability| Description | Implementation |
| ---- | ---------------------------------------- | ---------------------------------------- |
| Absolute positioning| Absolute positioning is poor in adaptability to devices of different sizes, and is prone to screen adaptation errors. | Use [position](../reference/arkui-ts/ts-universal-attributes-location.md) to implement absolute positioning and set the offset position of the upper left corner of an element relative to the upper left corner of the parent container. When laying out components, this attribute does not affect the layout of the parent component. It only adjusts the component position during drawing.|
| Relative positioning| Relative positioning keeps an element in the normal document flow, while allowing you to move it around relative to its original location.| You can use [offset](../reference/arkui-ts/ts-universal-attributes-location.md) to implement relative positioning and set the offset of an element relative to itself. This attribute does not affect the layout of the parent component. It only adjusts the component position during drawing.|
## Constraints on Child Components
| Constraint| Description | Implementation |
| --------- | ---------------------------------------- | ---------------------------------------- |
| Stretching | When the size of a container component changes, the increased or decreased amount of space is allocated to the specified area in the container component. | [flexGrow](../reference/arkui-ts/ts-universal-attributes-flex-layout.md) and [flexShrink](../reference/arkui-ts/ts-universal-attributes-flex-layout.md) attributes:<br>1. **flexGrow** defines the grow factor of a flex item.<br>2. **flexShrink** defines the shrink factor of a flex item.|
| Scaling | The width and height of a child component change with the container component, with its aspect ratio fixed at the preset value.| The [aspectRatio](../reference/arkui-ts/ts-universal-attributes-layout-constraints.md) attribute specifies the aspect ratio of the current component. The formula is as follows: aspectRatio = width/height.|
| Proportion | The proportion capability indicates that the width and height of child components change with the parent container component based on the preset proportion. | Two implementation modes are available with the universal attributes:<br>1. Set the width and height of the child components to a percentage of the width and height of the parent component.<br>2. Use the [layoutWeight](../reference/arkui-ts/ts-universal-attributes-size.md) attribute to enable the child components to adaptively occupy the remaining space.|
| Hiding | The hiding capability refers to that the visibility of a child component in a container component is subject to its preset display priority and the size of the container component. Child components with the same display priority are displayed or hidden at the same time.| The [displayPriority](../reference/arkui-ts/ts-universal-attributes-layout-constraints.md) attribute is used to control the visibility.|
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册