Introduction
In mobile application development, the consent mechanism for privacy policies and user agreements is a crucial环节 to protect user rights and comply with regulatory requirements. The PrivacyCheckbox
component in ZeroOneApp provides a fully functional and user-friendly solution for privacy agreement consent. This article will detailedly analyze its design philosophy, implementation details, and best practices.
Core Component Architecture
The PrivacyCheckbox
component is located in the project's common/ui
module at the path common/ui/src/main/ets/components/PrivacyCheckbox.ets
. It is a custom component developed based on the HarmonyOS ArkUI framework. The component mainly consists of the following parts:
File Structure
common/ui/src/main/ets/components/
└── PrivacyCheckbox.ets # Privacy agreement checkbox component
Core Dependencies
The component depends on utility classes and resource management modules in the project:
-
IntentUtil
: Used to handle page navigation after rich text clicks -
ResColor
: Provides unified color resource management -
loginComponentManager
: Defines the data structure and types for privacy text
Component Implementation Details
1. Component Property Definition
The component defines rich configurable parameters to support requirements in different scenarios:
@ComponentV2
export struct PrivacyCheckbox {
// Agreement content array
@Param texts: loginComponentManager.PrivacyText[] = [];
// Whether the agreement is checked
@Param isCheckboxSelected: boolean = false;
// Checkbox state change event
@Event boxChange: (select: boolean) => void;
// Unselected state animation trigger counter
@Param unselectAnimalCount: number = 0;
// Custom rich text click event
@Event onCustomItemClick?: (item: loginComponentManager.PrivacyText) => void;
// Animation-related properties
@Local translateX: number = 0;
}
2. UI Structure Design
The component adopts a Row-nested-Row layout structure to achieve horizontal arrangement of checkbox and text:
build() {
Row() {
// Checkbox part
Row() {
Checkbox(...) // Checkbox implementation
}
// Text content part
Row() {
Text() {
ForEach(this.texts, (item: loginComponentManager.PrivacyText) => {
// Render different styles according to text type
})
}
}
.layoutWeight(1)
.margin({ left: 12 })
}
.width('100%')
.alignItems(VerticalAlign.Top)
.justifyContent(FlexAlign.Start)
}
3. Core Checkbox Implementation
The checkbox is the core interactive element of the component, implementing state display, animation effects, and event callbacks:
Checkbox({ name: 'privacyCheckbox', group: 'privacyCheckboxGroup' })
.width(24)
.height(24)
.focusable(true)
.focusOnTouch(true)
.selectedColor(ResColor.themeLight())
.margin({ top: 0 })
.select(this.isCheckboxSelected)
.unselectedColor(this.translateX === 0 ? Color.Gray : Color.Red)
.translate({ x: this.translateX })
.animation({ curve: curves.springMotion() })
.onChange((value: boolean) => {
this.boxChange(value);
log.i(TAG, `agreementChecked: ${value}`);
})
4. Rich Text Processing Mechanism
The component supports mixed display of plain text and rich text, and provides click interaction for rich text:
ForEach(this.texts, (item: loginComponentManager.PrivacyText) => {
if (item?.type == loginComponentManager.TextType.PLAIN_TEXT && item?.text) {
// Plain text rendering
Span(item?.text)
.fontColor(ResColor.desc())
.fontWeight(FontWeight.Regular)
.fontSize($r('sys.float.ohos_id_text_size_body3'))
} else if (item?.type == loginComponentManager.TextType.RICH_TEXT && item?.text) {
// Rich text rendering
Span(item?.text)
.fontColor(ResColor.themeLight())
.fontWeight(FontWeight.Medium)
.fontSize($r('sys.float.ohos_id_text_size_body3'))
.focusable(true)
.focusOnTouch(true)
.onClick(() => {
// Rich text click handling
})
}
})
5. Unselected State Animation
To enhance user experience, the component implements a shaking animation in the unselected state to remind users to check the agreement:
@Monitor('unselectAnimalCount')
checkAgreeAnimate() {
if (this.isCheckboxSelected) {
return;
}
let count = 10;
let t = 0;
const id = setInterval(() => {
count -= 1;
if (count === 0) {
clearInterval(id);
this.translateX = 1;
return;
}
t += 30;
this.translateX = 30 * Math.sin(t);
}, 100)
}
Component Usage Methods
Basic Usage
PrivacyCheckbox({
texts: [
{ type: TextType.PLAIN_TEXT, text: 'I have read and agree to the' },
{ type: TextType.RICH_TEXT, text: 'User Agreement', tag: 'user_agreement' },
{ type: TextType.PLAIN_TEXT, text: 'and' },
{ type: TextType.RICH_TEXT, text: 'Privacy Policy', tag: 'privacy_policy' }
],
isCheckboxSelected: this.isAgree,
onCustomItemClick: (item) => {
// Custom click handling
},
boxChange: (isSelected) => {
this.isAgree = isSelected;
// Update button status and other operations
}
})
Text Data Structure
The loginComponentManager.PrivacyText
interface is defined as follows:
interface PrivacyText {
type: TextType; // PLAIN_TEXT or RICH_TEXT
text: string; // Display text
tag?: string; // Identifier for navigation
}
Advanced Features and Best Practices
1. Custom Rich Text Click Handling
The onCustomItemClick
event allows custom rich text click behavior, such as navigating to in-app pages instead of external links:
onCustomItemClick: (item) => {
if (item.tag === 'user_agreement') {
router.pushUrl({
url: 'pages/UserAgreementPage'
});
} else if (item.tag === 'privacy_policy') {
router.pushUrl({
url: 'pages/PrivacyPolicyPage'
});
}
}
2. Form Validation Integration
It is recommended to use the component with form validation to ensure users check the agreement before proceeding:
Button('Register')
.enabled(this.isAgree)
.onClick(() => {
// Execute registration logic
})
3. Animation Trigger Timing
Trigger the unselected state animation by modifying the unselectAnimalCount
property, typically used when users attempt to submit without checking the agreement:
if (!this.isAgree) {
this.unselectCount += 1; // Trigger animation
promptAction.showToast({
message: 'Please read and agree to the privacy agreement'
});
}
Summary and Outlook
The PrivacyCheckbox
component provides a compliant and user-friendly privacy agreement consent solution through elegant design and comprehensive functionality. Its main advantages include:
- Clear Structure: Adopts modular design with distinct code logic
- User-Friendly Interaction: Provides intuitive visual feedback and animation effects
- Highly Customizable: Supports custom text content, click behavior, and styles
- Easy Integration: Simple API design for quick project integration
Future enhancement considerations:
- Support for multilingual text display
- Adding agreement content collapse/expand functionality
- Implementing agreement version control mechanism
- Supporting dark/light mode adaptation
Top comments (0)