前言
本篇文章是使用 ArkTS 和 ArkUI 来搭建一个类似 QQ 登录页的一个页面,页面效果如下:
虽然页面看起来比较简单,但使用到的知识还是不少的。主要包含以下三部分内容:
- ArkTS 语言的基础内容:基本类型及关键字
- ArkUI 的基础组件的使用
- 容器组件:Row、Column
- UI 基础组件:Text、Image、TextInput、Toggle、Span、Button、AlertDialog
- 装饰器的介绍
- 组件装饰器:@Entry、@Component
- 状态装饰器:@State
废话不多说,让我们开始吧!
初始代码
首先,我们创建项目之后,Index.ets
文件中的默认代码如下:
scss
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
@Entry
装饰器用来修饰自定义组件,它装饰的自定义组件会被作为当前文件的 UI 入口。需要注意的是:每个 page 文件最多只能有一个 @Entry
装饰器修饰的组件,有多个是不可以的,比如下面的代码:
less
// 这是同一个文件的代码,如果是两个文件的代码则是没问题的。
@Entry
@Component
struct DetailPage {
build() {
}
}
@Entry
@Component
struct Test {
build() {
}
}
代码会编译报错:
@Component
装饰器只能修饰结构体这种数据结构,经它修饰的结构体会具有组件化的能力。一个结构体只能被一个 @Component
修饰,且该结构体内部必须实现 build()
函数。
介绍完 @Entry
和 @Component
装饰器,接下来讲解一下 @State
装饰器。
由 @State
修饰的变量称之为状态变量。它是所有状态变量相关的修饰其中最基础的,也是最常用的。它的作用就是其修饰的变量的值发生改变之后,用到该变量的组件会自动进行刷新。这就是声明式 UI 的动人之处。如果是命令式,比如 iOS 的传统方式,还需要变量的值修改之后,再去给相应的组件赋值。
ArtTS 基础语法
在正式编写组件之前,我们先来简单介绍一下 ArkTS 的基础语法。基本类型有以下三种:
- Boolean类型:由
true
和false
两个值组成。 - Number 类型:用来表示数字,包含整型和浮点数类型。
- String 类型:字符串类型。获取字符长度可以使用
length
来获取。
变量声明由 let
关键字实现,其修饰的变量可以被多次赋值;常量由 const
关键字修饰,变量只能被赋值一次。
示例代码如下:
ini
let result: boolean = true
let age: number = 3 // number 可以表示整型
let weight: number = 60.8 // number 可以表示浮点型
let name: string = 'jack'
name = 'rose'
const PI: number = 3.1415926
PI = 1 // 编译报错
Tips: ArkTS
是支持类型推断的,所以上述代码删除掉类型也是可以正常运行的。
页面搭建
容器组件 Column 和 Row
Column
和 Row
是 ArkUI 中最常用的两种线性布局。Column
是子组件纵向排列,它的主轴是垂直方向,交叉轴为水平方向;Row
是子组件横向排列,它的主轴为水平方向,交叉轴为垂直方向。
官网示例图如下:
在我们的例子中,组件是纵向排布的,所以外层我们需要使用 Column
:
less
@Entry
@Component
struct Index {
build() {
Column() { }
.width('100%')
}
}
Image - QQ 图标
ArkUI 是通过 Image
组件来显示本地或者网络图片。首先我们需要将本地图片放在项目中,示例目录如下:
将本地图片拖入项目之后,可以用下面的代码加载本地:
less
@Entry
@Component
struct Index {
build() {
Column() {
Image('images/qq.png')
.width(48)
}
.width('100%')
}
}
效果图如下:
虽然图片展示出来了,但是布局太靠顶部,所以我们需要用加一个 Row 来进行一个间隔:
scss
Row().height(50)
Image('images/qq.png')
.width(48)
输入框 - TextInput
我们需要提供两个输入框来让用户输入账号和密码,这就用到了 TextInput
组件。 示例代码如下:
scss
@Entry
@Component
struct Index {
@State accountText: string = ''
@State passwordText: string = ''
build() {
Column() {
Row().height(50)
Image('images/qq.png')
.width(48)
Row().height(100)
TextInput({text: this.accountText, placeholder: '输入QQ号'})
.type(InputType.Normal)
.margin(10)
.onChange((account) => {
this.accountText = account
})
TextInput({text: this.passwordText, placeholder: '输入QQ密码'})
.type(InputType.Password)
.margin(10)
.onChange((password) => {
this.passwordText = password
})
}
.width('100%')
}
}
首先,我们需要声明两个 @State
修饰的变量 accountText
和 passwordText
来保存用户的输入。接着初始化 TextInput
组件时传入了两个参数:
- text: 代表当前文本框的内容
- placeholder:当前文本框的占位符
接着通过 type
来设置当前输入框的类型:
- Normal:普通模式,什么字符都能输入。
- Password:密文模式,什么字符都能输入,但都会变成点。 其它类型请参见官方文档,本文未涉及就不展开讲了。
margin
用来设置外边距,这样输入框就不会紧贴着屏幕边缘。onChange
用来监听最新的输入内容。当前代码效果图如下:
文本 - Text 和 Span
输入框下面我们还需要展示一行文本,且该文本有两部分高亮可点击。这需要 Text
结合 Span
来使用。文本前面的勾选按钮可以使用 Toggle
组件。示例代码如下:
scss
@Entry
@Component
struct Index {
@State isSelectedProtocol: boolean = false
...
build() {
Column() {
....
Row() {
Toggle({ type: ToggleType.Checkbox, isOn: false })
.onChange((isOn) => {
this.isSelectedProtocol = isOn
})
Text() {
Span('已阅读并同意')
.fontColor(Color.Gray)
Span('服务协议')
.fontColor(Color.Blue)
.onClick(() => {
AlertDialog.show({
message: '点击了服务协议',
alignment: DialogAlignment.Center,
})
})
Span('和')
.fontColor(Color.Gray)
Span('QQ隐私保护指引')
.fontColor(Color.Blue)
.onClick(() => {
AlertDialog.show({
message: '点击了QQ隐私保护指引',
alignment: DialogAlignment.Center,
})
})
}
.fontSize(14)
}
}
.width('100%')
}
}
因为这是横向布局,所以在这几个组件外面包裹了 Row。
然后,声明一个状态变量 isSelectedProtocol
用来保存当前的协议选中状态。type
用来设置当前按钮的样式,共有下面三种类型:
- Checkbox
- Switch
- Button:需自己定义样式。
isOn
用来设置默认是否选中。
最后,借助 Text
和 Span
来展示文本。为了模拟高亮文本可点击,这里使用 AlertDialog
进行展示。
- fontSize:字体大小
- fontColor:字体颜色
- onClick:点击事件,在 ArkUI 里,文本也是可以添加点击事件的。
Tips:Span
只能作为 Text
组件的子组件显示文本内容。
当前代码效果图如下:
按钮 - Button
最后就是实现登录按钮了。
kotlin
@Entry
@Component
struct Index {
...
@State loginButtonEnable: boolean = false
build() {
Column() {
...
Row().height(20)
Button('登录')
.backgroundColor(
(this.isSelectedProtocol && this.accountText.length >0 && this.passwordText.length > 0) ? Color.Blue : Color.Gray)
.onClick(() => {
if ((this.isSelectedProtocol && this.accountText.length >0 && this.passwordText.length > 0)) {
AlertDialog.show({
message: '登录成功',
alignment: DialogAlignment.Center,
})
}
})
.width('90%')
}
.width('100%')
}
}
我们需要根据是否选中协议、账户是否有值和密码是否有值这三项来改变按钮的颜色,所以需要在 backgroundColor
用三目运算符给背景色赋值。登录效果同样也是用 AlertDialog 进行模拟。