47.HarmonyOS NEXT 登录模块开发教程(二):一键登录页面实现

embedded/2025/3/14 21:54:26/

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!

HarmonyOS NEXT 登录模块开发教程(二):一键登录页面实现

文章目录

  • HarmonyOS NEXT 登录模块开发教程(二):一键登录页面实现
    • 效果预览
    • 1. 引言
    • 2. DefaultLogin 组件概述
      • 2.1 组件功能
      • 2.2 组件结构
    • 3. DefaultLogin 组件实现
      • 3.1 完整代码
      • 3.2 状态变量解析
        • 3.2.1 @Link 装饰器
        • 3.2.2 @State 装饰器
        • 3.2.3 TransitionEffect
    • 4. UI 布局详解
      • 4.1 整体布局
      • 4.2 用户信息区域
    • 总结

效果预览

1. 引言

在上一篇教程中,我们介绍了 HarmonyOS NEXT 登录模块的整体架构和模态窗口的实现原理。本篇教程将深入讲解 DefaultLogin 组件的实现,这是登录模块中最核心的组件之一,负责提供默认的一键登录页面。

一键登录是现代移动应用中常见的登录方式,它能够简化用户的登录流程,提高用户体验。在 HarmonyOS NEXT 中,我们可以通过 ArkTS 语言和声明式 UI 框架,轻松实现一个功能完善的一键登录页面。

2. DefaultLogin 组件概述

2.1 组件功能

DefaultLogin 组件主要提供以下功能:

  1. 显示用户头像和欢迎信息
  2. 展示用户手机号(预设或从系统获取)
  3. 提供服务协议阅读和同意选项
  4. 实现一键登录按钮及其交互逻辑
  5. 提供其他登录方式的入口
  6. 支持返回按钮,控制模态窗口的显示/隐藏

2.2 组件结构

部分描述
状态变量控制组件内部状态和 UI 展示
DefaultLoginPage构建一键登录页面 UI 的 Builder 函数
build 方法组件的主要构建方法,处理页面切换逻辑

3. DefaultLogin 组件实现

3.1 完整代码

import promptAction from '@ohos.promptAction';
import { OtherWaysToLogin, ReadAgreement } from './OtherWaysToLogin';const EFFECT_DURATION = 800;
const EFFECT_OPACITY = 0.4;
const SPACE_TEN = 10;@Component
export struct DefaultLogin {/*** isPresentInLoginView控制登录页面是否显示* 子组件中被@Link装饰的变量与其父组件中@State装饰的对应数据源建立双向数据绑定,详见:* https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link-0000001820999565*/@Link isPresentInLoginView: boolean;// 是否是默认一键登录方式@State isDefaultLogin: boolean = true;// 用户名userName: string = '18888888888';// 判断是否同意协议isConfirmed: boolean = false;private effect: TransitionEffect = TransitionEffect.OPACITY.animation({ duration: EFFECT_DURATION }).combine(TransitionEffect.opacity(EFFECT_OPACITY))// 默认一键登录方式@BuilderDefaultLoginPage() {Column({ space: SPACE_TEN }) {Row({ space: SPACE_TEN }) {Image($r('app.media.batman')).width($r('app.integer.modalwindow_user_image_height')).height($r('app.integer.modalwindow_user_image_height'))Column({ space: SPACE_TEN }) {Text($r('app.string.modalwindow_welcome_back')).fontWeight(FontWeight.Bold).fontSize($r('app.integer.modalwindow_font_size_mid')).fontColor(Color.Black)Text($r('app.string.modalwindow_more_wonderful_after_login')).fontColor($r('app.color.modalwindow_grey_3'))}.alignItems(HorizontalAlign.Start)}.alignItems(VerticalAlign.Center).width($r('app.string.modalwindow_size_full'))Text(this.userName).fontColor($r('app.color.modalwindow_grey_3')).fontWeight(FontWeight.Bold).padding({ left: $r('app.integer.modalwindow_padding_default') }).height($r('app.integer.modalwindow_user_image_height')).width($r('app.string.modalwindow_size_full')).borderRadius($r('app.integer.modalwindow_border_radius')).backgroundColor($r('app.color.modalwindow_grey_e'))Text($r('app.string.modalwindow_verify_server_tip')).fontColor($r('app.color.modalwindow_grey_6')).width($r('app.string.modalwindow_size_full')).textAlign(TextAlign.Start)Row() {Checkbox({ name: 'checkbox1' }).id('default_agreement').select(this.isConfirmed).onChange((value: boolean) => {this.isConfirmed = value})ReadAgreement()}.width($r('app.string.modalwindow_size_full')).alignItems(VerticalAlign.Center)Button($r('app.string.modalwindow_phone_start_login')).fontColor(Color.White).borderRadius($r('app.integer.modalwindow_border_radius')).type(ButtonType.Normal).backgroundColor($r('app.color.modalwindow_grey_2')).onClick(() => {if (this.isConfirmed) {// 调用Toast显示登录成功提示promptAction.showToast({ message: $r('app.string.modalwindow_login_success') });} else {// 调用Toast显示请先阅读并同意协议提示promptAction.showToast({ message: $r('app.string.modalwindow_please_read_and_agree') });}}).width($r('app.string.modalwindow_size_full')).height($r('app.integer.modalwindow_height_fifty'))Row() {Text($r('app.string.modalwindow_other_way_login')).fontColor($r('app.color.modalwindow_grey_7')).backgroundColor($r('app.color.modalwindow_transparent_7')).onClick(() => {this.isDefaultLogin = false;})Blank() // 在容器主轴方向上自动填充容器空余部分Text($r('app.string.modalwindow_login_problems')).fontColor($r('app.color.modalwindow_grey_7')).backgroundColor($r('app.color.modalwindow_transparent_7')).onClick(() => {// 调用Toast显示遇到问题提示promptAction.showToast({ message: $r('app.string.modalwindow_login_problems') });})}.width($r('app.string.modalwindow_size_full'))}.width($r('app.string.modalwindow_size_full')).height($r('app.string.modalwindow_size_full')).backgroundColor(Color.White).justifyContent(FlexAlign.Center)}build() {Stack({ alignContent: Alignment.TopStart }) {// 登录方式有两种(默认一键登录方式和其他方式登录),需要在一个模态窗口中切换,使用if进行条件渲染if (this.isDefaultLogin) {this.DefaultLoginPage() // 默认一键登录方式} else {OtherWaysToLogin()// 其他登录方式.transition(this.effect) // 此处涉及到组件的显示和消失,所以使用transition属性设置出现/消失转场}Image($r('app.media.arrow_back'))// 通过Stack组件,两个页面只实现一个back.id('login_back').width($r('app.integer.modalwindow_height_twenty_five')).height($r('app.integer.modalwindow_height_twenty_five')).margin({ top: $r('app.integer.modalwindow_margin_mid') }).onClick(() => {if (this.isDefaultLogin) {this.isPresentInLoginView = false;} else {this.isDefaultLogin = true}})}.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]).size({ width: $r('app.string.modalwindow_size_full'), height: $r('app.string.modalwindow_size_full') }).padding({top: $r('app.integer.modalwindow_padding_default'),left: $r('app.integer.modalwindow_padding_default'),right: $r('app.integer.modalwindow_padding_default')}).backgroundColor(Color.White) // 将模态页面背景设置为白色,以避免模态页面内组件发生显隐变化时露出下层页面}
}

3.2 状态变量解析

在 DefaultLogin 组件中,我们定义了以下状态变量:

@Link isPresentInLoginView: boolean;
@State isDefaultLogin: boolean = true;
userName: string = '18888888888';
isConfirmed: boolean = false;
private effect: TransitionEffect = TransitionEffect.OPACITY.animation({ duration: EFFECT_DURATION }).combine(TransitionEffect.opacity(EFFECT_OPACITY))
变量名装饰器类型作用
isPresentInLoginView@Linkboolean与父组件建立双向数据绑定,控制模态窗口的显示/隐藏
isDefaultLogin@Stateboolean控制当前显示的是默认登录页面还是其他登录方式页面
userNamestring存储用户手机号,此处为预设值
isConfirmedboolean记录用户是否同意服务协议
effectprivateTransitionEffect定义页面切换时的转场效果
3.2.1 @Link 装饰器

@Link装饰器用于在父子组件之间建立双向数据绑定。在我们的例子中,DefaultLogin 组件通过@Link 装饰的 isPresentInLoginView 变量与 ModalWindowComponent 中的 isPresent 变量建立了双向绑定。

当 DefaultLogin 组件中修改 isPresentInLoginView 的值时,ModalWindowComponent 中的 isPresent 也会同步更新,反之亦然。这种机制使得子组件可以控制父组件中的状态,实现更灵活的组件通信。

3.2.2 @State 装饰器

@State装饰器用于声明组件的内部状态。当@State 装饰的变量值发生变化时,框架会自动重新渲染组件。在 DefaultLogin 组件中,isDefaultLogin 变量控制显示默认登录页面还是其他登录方式页面。

3.2.3 TransitionEffect

TransitionEffect 用于定义组件的转场效果。在 DefaultLogin 组件中,我们定义了一个组合转场效果,包括透明度变化和动画持续时间:

private effect: TransitionEffect = TransitionEffect.OPACITY.animation({ duration: EFFECT_DURATION }).combine(TransitionEffect.opacity(EFFECT_OPACITY))

这个转场效果会在默认登录页面和其他登录方式页面之间切换时应用,提供平滑的视觉过渡。

4. UI 布局详解

4.1 整体布局

DefaultLogin 组件的 UI 布局采用嵌套的容器组件实现,主要包括:

  1. 最外层使用 Stack 组件,实现页面切换和返回按钮的叠加布局
  2. 内部使用 Column 组件作为主要容器,垂直排列各个 UI 元素
  3. 使用 Row 组件实现水平排列的元素,如用户头像和欢迎信息

4.2 用户信息区域

让我详细讲解这段用户信息区域的代码:

Row({ space: SPACE_TEN }) {  // 创建水平布局,设置子元素间距为10// 1. 用户头像Image($r('app.media.batman'))  // 加载本地图片资源.width($r('app.integer.modalwindow_user_image_height'))  // 设置图片宽度.height($r('app.integer.modalwindow_user_image_height')) // 设置图片高度// 2. 欢迎信息区域Column({ space: SPACE_TEN }) {  // 创建垂直布局,子元素间距为10// 2.1 欢迎回来文本Text($r('app.string.modalwindow_welcome_back')).fontWeight(FontWeight.Bold)    // 设置字体粗细为粗体.fontSize($r('app.integer.modalwindow_font_size_mid'))  // 设置字体大小.fontColor(Color.Black)         // 设置字体颜色为黑色// 2.2 登录后更精彩提示文本Text($r('app.string.modalwindow_more_wonderful_after_login')).fontColor($r('app.color.modalwindow_grey_3'))  // 设置字体颜色为灰色}.alignItems(HorizontalAlign.Start)  // 将Column内的文本左对齐
}
.alignItems(VerticalAlign.Center)  // Row内的元素垂直居中对齐
.width($r('app.string.modalwindow_size_full'))  // 设置整个Row的宽度为100%

代码结构分析:

  1. 外层容器

    • 使用 Row 组件创建水平布局
    • space: SPACE_TEN 设置子元素间距为 10 像素
    • .alignItems(VerticalAlign.Center) 使子元素垂直居中
    • .width($r('app.string.modalwindow_size_full')) 使容器宽度占满父容器
  2. 头像部分

    • 使用 Image 组件显示用户头像
    • 通过 $r('app.media.batman') 引用本地图片资源
    • 使用资源引用设置宽高,保证在不同设备上的一致性
  3. 文字信息部分

    • 使用 Column 组件创建垂直布局
    • 包含两个 Text 组件:
      • 欢迎语:粗体显示,黑色
      • 提示语:使用灰色显示
    • .alignItems(HorizontalAlign.Start) 确保文本左对齐

布局效果:

  • 左侧显示圆形头像
  • 右侧垂直排列两行文本
  • 整体垂直居中对齐
  • 文本左对齐排列
  • 组件间保持统一的间距

总结

本文详细介绍了 HarmonyOS NEXT 登录模块中 DefaultLogin 组件的实现,主要包括以下几个方面:

  1. 组件架构设计

    • 采用 ArkTS 声明式开发范式
    • 使用装饰器(@Link、@State)管理组件状态
    • 实现页面间平滑切换的转场效果
  2. UI 布局实现

    • 使用 Stack、Column、Row 等布局组件构建界面
    • 运用资源引用($r)确保界面在不同设备上的一致性
    • 实现了用户信息展示、协议确认、登录按钮等核心功能
  3. 交互功能

    • 实现一键登录和其他登录方式的切换
    • 添加服务协议确认机制
    • 集成返回按钮和页面导航功能
  4. 最佳实践

    • 组件状态管理的规范使用
    • UI 布局的模块化设计
    • 代码复用和维护性的考虑

通过本教程,开发者可以了解如何在 HarmonyOS NEXT 中实现一个功能完整、交互友好的登录页面,同时掌握 ArkTS 组件开发的核心概念和最佳实践。这些知识和技能可以应用到其他类似的组件开发中,帮助开发者构建更好的 HarmonyOS 应用。


http://www.ppmy.cn/embedded/172584.html

相关文章

flutter EventBus 的使用介绍

一、EventBus 初识 EventBus 是一个只有20多行的代码库, 通常用它来做事件分发。 EventBus 遵从 publish/subscribe 模式,即发布/订阅模式;简化了模块之间通信,对于项目的解耦很实用; 组件地址: https://github.com/marcojakob/dart-event-bus 源码: class EventBus…

Swift 手动导入 RxSwift.xcframework 报错

0x00 问题 The signature of “RxCocoa.xcframework” cannot be validated and may have been compromised. Validation Error: A sealed resource is missing or invalid 0x01 办法 手动修复签名,能 Build 成功! 打开终端,重新签名&…

WPS二次开发系列:Android 第三方应用如何获取WPS端内文档

1.需求场景 在项目开发中碰到这种情况,我们需要利用WPS的文档管理能力,比如需要调用WPS的文件选择器,来选择文档,同时需要得到WPS选择的文档结果返回给我们的应用。之前在网上找到了很久都没有找到WPS移动端有相关的API接口文档和…

计算机视觉算法实战——驾驶员玩手机检测(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​ 1. 领域简介:玩手机检测的重要性与技术挑战 驾驶员玩手机检测是智能交通安全领域的核心课题。根据NHTSA数据&#xff0…

Golang | 每日一练 (5)

💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (5)题目参考答案线程与协程线程切换…

ArcGIS 水利制图符号库:提升水利工作效率的利器

引言 在当今数字化时代,地理信息系统(GIS)技术已深入渗透到各个领域,水利行业也不例外。ArcGIS 作为 GIS 领域的佼佼者,为水利工程设计、管理与分析提供了强大工具。而 ArcGIS 水利制图符号库的出现,更是为…

【小白向】Ubuntu|VMware 新建虚拟机后打开 SSH 服务、在主机上安装vscode并连接、配置 git 的 ssh

常常有人问VMware-Tools装了也复制粘贴不了怎么办,这个东西影响因素太多了,具体解决办法你们可以参考一下:【经验】VMware|虚拟机只能使用鼠标无法使用键盘、装不了或装了VMware-Tools无法复制粘贴的可能解决办法_增强型键盘驱动程…

初次体验Tauri和Sycamore(3)通道实现

​ 原创作者:庄晓立(LIIGO) 原创时间:2025年03月10日(发布时间) 原创链接:https://blog.csdn.net/liigo/article/details/146159327 版权所有,转载请注明出处。 20250310 LIIGO备注&…