ArkUI TextInput:输入框写得顺,用户才愿意继续填
ArkUI TextInput:输入框写得顺,用户才愿意继续填
这篇我们写 TextInput。输入框很小,但它特别容易暴露页面粗糙感:占位文字太重、键盘类型不对、密码框没有眼睛图标、错误态只靠用户自己猜。
所以这个案例不做完整登录页,也不讲状态管理。我们先把输入框本体看清楚:普通输入、手机号、邮箱、验证码、密码、错误态和禁用态。
参考文档:
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkui
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development
普通输入框先别写得太硬
一个舒服的输入框,通常不是靠大改结构,而是把几个小地方调顺。
TextInput({ placeholder: '请输入昵称' })
.width('100%')
.height(44)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.placeholderFont({ size: 14, weight: 400 })
.caretColor('#2563EB')
.maxLength(16)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#CBD5E1' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
这里的 placeholderColor 故意放轻一点。占位文字只是提示,不应该和用户真正输入的内容抢注意力。
caretColor 是光标颜色。页面主色是蓝色时,光标也跟着走,细节会统一一些。
maxLength(16) 是很实用的小限制。昵称这种字段一般不需要无限长,提前限制比后面再拦截更直观。
输入类型要顺手
手机号、邮箱、验证码都能用普通输入框写,但用户体验会差一点。type 的价值就在这里:让系统给出更合适的输入方式。
TextInput({ placeholder: '请输入手机号' })
.type(InputType.PhoneNumber)
.enterKeyType(EnterKeyType.Next)
.maxLength(11)
TextInput({ placeholder: 'name@example.com' })
.type(InputType.Email)
.enterKeyType(EnterKeyType.Done)
手机号用 PhoneNumber,邮箱用 Email。这一步很简单,但新手很容易忘,然后所有输入框都停留在默认类型。
enterKeyType 控制软键盘右下角的动作提示。手机号后面还有别的字段,就用 Next;邮箱已经是最后一步,就可以用 Done。
验证码这里多加了一个 inputFilter:
TextInput({ placeholder: '6 位数字验证码' })
.type(InputType.Number)
.inputFilter('[0-9]')
.maxLength(6)
inputFilter('[0-9]') 表示只让数字字符显示出来。它适合这种很明确的字段。别把所有输入都塞过滤规则,字段越复杂,越应该把校验留给更完整的表单逻辑。
密码框要给用户一点掌控感
密码输入只改 type 还不够。一般来说,我们还会让用户能切换显示和隐藏。
TextInput({ placeholder: '请输入密码' })
.type(InputType.Password)
.showPasswordIcon(true)
.maxLength(20)
InputType.Password 会按密码输入处理,showPasswordIcon(true) 会显示眼睛图标。这个交互很常见,用户也熟,不需要我们额外解释太多。
错误态和禁用态要一眼看懂
错误输入不要只靠红边框暗示。能直接告诉用户问题在哪,就直接说。
TextInput({ text: 'hi', placeholder: '用户名至少 4 个字符' })
.showError('用户名太短')
.border({ width: 1, color: '#FCA5A5' })
showError 适合展示输入框自己的错误提示。这个案例没有写提交按钮,也没有写表单校验流程,是因为那会把主题带到状态管理和业务逻辑里。我们后面写状态章节时再把它补完整。
禁用态也一样,要让它看起来明显不能编辑:
TextInput({ text: 'WELCOME-2026', placeholder: '邀请码' })
.enabled(false)
.backgroundColor('#E2E8F0')
.fontColor('#64748B')
别只调用 enabled(false) 就结束。颜色、背景、边框都安静一点,用户才不会误以为它还能点。
看案例时盯这几处
打开案例页后,可以顺着这几个点看:
- 昵称输入框的占位文字是否足够轻。
- 手机号和邮箱是否用了不同的输入类型。
- 验证码是否只能输入数字,并限制在 6 位。
- 密码框是否出现显示/隐藏图标。
- 错误态和禁用态是否能一眼分清。
这篇不跑 hvigor。你在 DevEco Studio 里打开案例页,手动点进几个输入框,看键盘、光标和输入限制是否符合预期就行。
如果你现在项目里有表单,可以先只挑一个输入框改:把 placeholderColor、type、maxLength 这三个补上。你最常写的是哪类输入框?手机号、搜索框、评论框,还是登录密码?这个问题其实会决定下一篇 TextArea 或搜索输入要不要提前写。
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/basic/ArkUITextInputDemo.ets
@Entry
@Component
struct ArkUITextInputDemo {
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 4 }) {
Text(title)
.width('100%')
.fontSize(16)
.fontWeight(700)
.fontColor('#0F172A')
Text(desc)
.width('100%')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
@Builder
inputLabel(label: string) {
Text(label)
.width('100%')
.fontSize(13)
.fontWeight(600)
.fontColor('#334155')
}
build() {
Scroll() {
Column({ space: 18 }) {
Text('ArkUI TextInput')
.width('100%')
.fontSize(24)
.fontWeight(700)
.fontColor('#0F172A')
Text('输入框写得顺,用户才愿意继续填')
.width('100%')
.fontSize(22)
.fontWeight(700)
.fontColor('#111827')
Text('这一页不做登录表单,也不讲状态管理。我们只把 TextInput 自己的几个常用细节摆清楚:占位提示、输入类型、长度限制、密码显示和错误提示。')
.width('100%')
.fontSize(14)
.fontColor('#64748B')
.lineHeight(22)
Column({ space: 12 }) {
this.sectionTitle('先把一个普通输入框写舒服', '占位文字要轻一点,光标颜色跟主色走,输入区域高度也别太挤。')
this.inputLabel('昵称')
TextInput({ placeholder: '请输入昵称' })
.width('100%')
.height(44)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.placeholderFont({ size: 14, weight: 400 })
.caretColor('#2563EB')
.maxLength(16)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#CBD5E1' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
}
.width('100%')
.padding(16)
.backgroundColor('#F8FAFC')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('输入类型别全用默认值', '手机号、邮箱、验证码的键盘和输入规则不一样,type 写对,用户少切几次键盘。')
this.inputLabel('手机号')
TextInput({ placeholder: '请输入手机号' })
.width('100%')
.height(44)
.type(InputType.PhoneNumber)
.enterKeyType(EnterKeyType.Next)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.caretColor('#0F766E')
.maxLength(11)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#99F6E4' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
this.inputLabel('邮箱')
TextInput({ placeholder: 'name@example.com' })
.width('100%')
.height(44)
.type(InputType.Email)
.enterKeyType(EnterKeyType.Done)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.caretColor('#0F766E')
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#99F6E4' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
this.inputLabel('验证码,只允许输入数字')
TextInput({ placeholder: '6 位数字验证码' })
.width('100%')
.height(44)
.type(InputType.Number)
.inputFilter('[0-9]')
.maxLength(6)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.caretColor('#0F766E')
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#99F6E4' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
}
.width('100%')
.padding(16)
.backgroundColor('#F0FDFA')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('密码框别忘了眼睛图标', 'Password 类型会按密码输入处理,showPasswordIcon 可以让用户自己切换显示和隐藏。')
this.inputLabel('密码')
TextInput({ placeholder: '请输入密码' })
.width('100%')
.height(44)
.type(InputType.Password)
.showPasswordIcon(true)
.maxLength(20)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.caretColor('#7C3AED')
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#DDD6FE' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
}
.width('100%')
.padding(16)
.backgroundColor('#F5F3FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('错误态和禁用态要看得出来', '错误信息别只靠红色边框猜,不能编辑时也要让输入框明显安静下来。')
this.inputLabel('用户名')
TextInput({ text: 'hi', placeholder: '用户名至少 4 个字符' })
.width('100%')
.height(44)
.fontSize(15)
.fontColor('#0F172A')
.placeholderColor('#94A3B8')
.caretColor('#DC2626')
.showError('用户名太短')
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#FCA5A5' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
this.inputLabel('邀请码')
TextInput({ text: 'WELCOME-2026', placeholder: '邀请码' })
.width('100%')
.height(44)
.fontSize(15)
.fontColor('#64748B')
.enabled(false)
.backgroundColor('#E2E8F0')
.border({ width: 1, color: '#CBD5E1' })
.borderRadius(8)
.padding({ left: 12, right: 12 })
}
.width('100%')
.padding(16)
.backgroundColor('#FFF7ED')
.borderRadius(8)
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
- 点赞
- 收藏
- 关注作者
评论(0)