移动应用中,"提交表单"是最常见的用户交互模式之一。用户选择分类、填写内容、留下联系方式——三个步骤完成了从"想法"到"反馈"的信息流转。HarmonyOS NEXT ArkUI 提供了 Select(下拉选择器)和 TextArea(多行文本输入框)两个核心组件,它们与 TextInput(单行输入框)组合,可以构建出完整、专业的表单页面。

本文将深入讲解 Select 和 TextArea 组件的使用方法,并构建一个完整的"用户反馈与建议"应用——支持分类选择、内容填写、联系方式输入、表单验证和历史记录管理。

关键词:HarmonyOS、ArkUI、Select、TextArea、下拉选择器、多行输入、表单验证、用户反馈

一、Select 下拉选择器

1.1 API 概述

Select 是 ArkUI 提供的下拉选择组件。点击组件区域后弹出选项菜单,用户选择一个选项后菜单关闭,选中的值显示在组件上。

Select([
  { value: '功能建议' },
  { value: '问题反馈' },
  { value: '使用咨询' },
  { value: '其他' }
])
  .selected(0)                              // 默认选中第 0 项
  .value('功能建议')                         // 显示文本(与选中项同步)
  .font({ size: 14 })                       // 文本样式
  .selectedOptionBgColor('#F0F5FF')          // 选中项背景色
  .optionBgColor('#FFFFFF')                  // 选项背景色
  .onSelect((index: number, value: string) => {
    // index: 选中项索引(从 0 开始)
    // value: 选中项的文本值
    this.categoryIndex = index;
  })

核心属性与回调:

  • 构造函数参数Array<SelectOption>,每个 SelectOption 包含 value(必填,选项文本)和可选的 icon(选项图标)
  • selected(index):预设选中项的索引。通常在页面初始化时设为 0(第一项),用户选择后更新
  • value(string):组件上显示的文本。通常与 selected 指针对应的选项值同步
  • font(Font):文本字体样式,包含 size(字号)和 weight(粗细)。注意:颜色通过 .fontColor() 单独设置,不在 Font 对象内
  • selectedOptionBgColor(color):下拉菜单中当前选中项的背景颜色,用于高亮当前选择
  • optionBgColor(color):下拉菜单中所有选项的背景颜色
  • onSelect(callback):用户选择选项后触发,回调参数为选中项的索引和文本值

1.2 SelectOption 接口

interface SelectOption {
  value: ResourceStr;           // 必填:选项文本
  icon?: ResourceStr;           // 可选:选项图标
  symbolIcon?: SymbolGlyphModifier;  // API 12+:Symbol 图标
}

本文 Demo 使用最简单的纯文本选项:

Select([
  { value: '功能建议' },
  { value: '问题反馈' },
  { value: '使用咨询' },
  { value: '其他' }
])

如需图标,可以传入 icon 字段(如 $r('app.media.icon_suggestion')),图标会显示在文字左侧。

1.3 同步 selected 与 value

selected 是索引(0-based),value 是对应的展示文本。两者需要保持同步——当用户通过 onSelect 选择了新选项,需要同步更新 selectedvalue

@State categoryIndex: number = 0;
@State categoryValue: string = '功能建议';

// 错误的做法(不同步):
Select([...])
  .selected(this.categoryIndex)     // 用户选择后 index 变了
  .value('功能建议')                // 但 value 仍然是硬编码的默认值

// 正确的做法(同步更新):
Select([...])
  .selected(this.categoryIndex)
  .value(this.categories[this.categoryIndex])  // 与 selected 指向同一项
  .onSelect((index: number, value: string) => {
    this.categoryIndex = index;     // 同步更新索引
  })

本文 Demo 使用数组索引访问模式——this.getCategories()[this.categoryIndex]——确保 value 始终与 selected 指向的选项一致。

1.4 样式定制

Select 的样式中一个容易出错的地方:颜色不在 .font()。ArkUI 的 Font 类型只包含 sizeweight,颜色需要通过 .fontColor() 设置:

// 正确
Select([...])
  .font({ size: 14 })
  .fontColor('#1a1a2e')

// 错误 —— 编译报错:"color does not exist in type 'Font'"
Select([...])
  .font({ size: 14, color: '#1a1a2e' })

这个设计与普通 Text 组件一致——.fontSize().fontColor() 是分开的属性。

二、TextArea 多行输入框

2.1 API 概述

TextArea 是 ArkUI 的多行文本输入组件,支持长文本的输入和编辑。

TextArea({ text: this.content, placeholder: '请详细描述您的建议或问题' })
  .fontSize(14)
  .height(140)
  .borderRadius(8)
  .backgroundColor('#F8F9FA')
  .onChange((value: string) => {
    this.content = value;
    this.contentLength = value.length;
  })

核心属性与回调:

  • text:输入框的文本内容(双向绑定,通过 @State 变量控制)
  • placeholder:占位提示文本,输入框为空时显示,灰色字
  • height:输入框高度。TextArea 需要显式设置高度,否则可能只有一行高
  • onChange(callback):文本内容变化时触发,回调参数为当前完整文本内容

2.2 与 TextInput 的区别

特性 TextArea TextInput
行数 多行(需设 height) 单行(固定高度)
换行 支持回车换行 不支持(回车提交)
适用场景 正文输入、描述、反馈内容 标题、姓名、手机号、URL
建议高度 120-200vp 40-48vp
滚动 内容超出高度时自动滚动 不滚动

本文 Demo 将 TextArea 用于"反馈内容"(多行正文),将 TextInput 用于"联系方式"(单行短文),清晰展示了两个组件的场景差异。

2.3 实时字数统计

TextArea 的 onChange 回调可用于实时统计字数:

@State content: string = '';
@State contentLength: number = 0;

TextArea({ text: this.content, placeholder: '...' })
  .onChange((value: string) => {
    this.content = value;
    this.contentLength = value.length;
  })

// 显示字数,10字以上变绿
Text(this.contentLength.toString().concat(' 字'))
  .fontColor(this.contentLength >= 10 ? '#00B894' : '#BBBBCC')

字数颜色在达到最低要求(10 字)后从灰色变为绿色——这是一种"即时反馈"设计:用户在打字的同时就知道距离"可提交"还差多少。
在这里插入图片描述

三、反馈表单的完整设计

3.1 页面架构

本文 Demo 构建一个"用户反馈与建议"应用:

FeedbackPage
├── 标题栏 — "反馈与建议" + 记录计数
├── 组件说明卡片 — Select + TextArea 介绍
├── 反馈表单
│   ├── 反馈类型(Select 下拉选择)
│   ├── 反馈内容(TextArea 多行输入 + 字数统计)
│   ├── 联系方式(TextInput 单行输入,选填)
│   └── 提交按钮(满足条件后激活)
├── 提交成功提示 + 继续反馈按钮
└── 反馈记录列表(按时间倒序)

3.2 数据结构

interface FeedbackRecord {
  id: number;
  category: string;   // '功能建议' | '问题反馈' | '使用咨询' | '其他'
  content: string;    // 反馈正文
  contact: string;    // 联系方式
  date: string;       // 提交时间
}

@State history: FeedbackRecord[] = [];
@State nextId: number = 1;

每条反馈记录包含类型、内容、联系方式、提交时间。新提交的记录通过 concat 插入数组头部(最新的在最上面):

this.history = [record].concat(this.history.slice());

slice() 创建副本,确保 @State 能检测到引用变化并触发 UI 更新。

3.3 表单验证

提交按钮仅当内容满足最低要求时激活:

canSubmit(): boolean {
  return this.content.trim().length >= 10;
}

按钮样式根据验证状态动态切换:

  • 内容 < 10 字:灰色背景(.backgroundColor('#CCCCDD')),不可点击感
  • 内容 >= 10 字:蓝色背景(.backgroundColor('#1677FF')),可点击

这是"前端验证"中最基本的模式——在 submit 之前就告诉用户"还差什么",而不是点击后才弹出错误提示。

3.4 提交与重置

submitFeedback(): void {
  if (!this.canSubmit()) return;
  let record: FeedbackRecord = {
    id: this.nextId,
    category: this.getCategories()[this.categoryIndex],
    content: this.content.trim(),
    contact: this.contact.trim(),
    date: this.formatDate()
  };
  this.nextId++;
  this.history = [record].concat(this.history.slice());
  this.submitted = true;
}

提交成功后 submitted = true,表单区域上方显示成功提示卡片,包含"继续反馈"按钮。点击"继续反馈"调用 resetForm()

resetForm(): void {
  this.categoryIndex = 0;
  this.content = '';
  this.contact = '';
  this.contentLength = 0;
  this.submitted = false;
}

重置后所有字段回到初始状态,用户可以提交下一条反馈。
在这里插入图片描述

四、反馈记录展示

4.1 分类标签

历史记录中,每条反馈的分类使用彩色标签显示:

getCategoryColor(cat: string): string {
  if (cat === '功能建议') return '#1677FF';  // 蓝色
  if (cat === '问题反馈') return '#FF4D4F';  // 红色
  if (cat === '使用咨询') return '#E09F3E';  // 橙色
  return '#636E72';                          // 灰色
}

不同颜色帮助用户快速区分反馈类型——红色的问题反馈一眼可见,蓝色的功能建议温和友好。

4.2 记录卡片布局

每条记录显示:

  • 分类标签(彩色背景,白色文字)
  • 提交时间(灰色,右上角)
  • 反馈内容(黑色正文,最多 3 行省略)
  • 联系方式(如有填写)

卡片之间用 Divider 分隔,视觉层次清晰。

4.3 空状态

history.length === 0 时,整个"反馈记录"区域隐藏。只有在用户提交至少一条反馈后,历史记录区域才出现。这是一个渐进式信息披露的设计——不提前展示空列表容器,页面在初始状态下更简洁。

五、Select 的高级特性

5.1 箭头位置

通过 arrowPosition 控制下拉箭头的显示位置:

Select([...])
  .arrowPosition(ArrowPosition.START)  // 箭头在左侧
  .arrowPosition(ArrowPosition.END)    // 箭头在右侧(默认)

5.2 菜单对齐

通过 menuAlign 控制下拉菜单与 Select 组件的对齐方式:

Select([...])
  .menuAlign(MenuAlignType.START)   // 菜单左对齐
  .menuAlign(MenuAlignType.CENTER)  // 菜单居中
  .menuAlign(MenuAlignType.END)     // 菜单右对齐

5.3 选项字体与背景

除了全局的 .font().fontColor(),还有针对选项的样式:

Select([...])
  .optionFont({ size: 14 })         // 选项字体
  .optionFontColor('#1a1a2e')       // 选项文字颜色
  .selectedOptionBgColor('#F0F5FF') // 选中项背景色
  .optionBgColor('#FFFFFF')         // 未选中项背景色

六、TextArea 的高级特性

6.1 最大字符限制

TextArea({ text: this.content })
  .maxLength(500)  // 最多 500 字符

设置 maxLength 后,用户在达到限制后无法继续输入。结合字数统计显示 “125 / 500”,可以给用户明确的边界感。

6.2 自定义键盘类型

TextArea({ text: this.content })
  .type(InputType.Normal)   // 默认键盘
  .enterKeyType(EnterKeyType.NewLine)  // 回车键行为

对于反馈场景,通常使用 .enterKeyType(EnterKeyType.NewLine)(回车换行),而不是 Send/Go。

6.3 TextAreaController

类似 TextTimer 的 controller,TextArea 也有 TextAreaController:

private controller: TextAreaController = new TextAreaController();

// 通过 controller 操作
this.controller.caretPosition(10);  // 光标定位到第 10 个字符后

七、交互流程演示

7.1 首次进入

页面展示空白表单。Select 默认选中"功能建议",TextArea 显示占位提示"请详细描述您的建议或问题(至少10个字)“,字数统计显示"0 字”(灰色),提交按钮为灰色不可点击状态。

7.2 填写表单

用户选择分类为"问题反馈"(Select 弹出菜单,点击"问题反馈",菜单关闭,组件显示"问题反馈")。在 TextArea 中输入问题描述,字数统计实时更新。当达到 10 字时,数字变为绿色,提交按钮变为蓝色。

7.3 提交成功

点击"提交反馈",成功提示卡片显示:绿色对勾、感谢文字、"继续反馈"按钮。表单自动隐藏(submitted = true 时,表单区域仍可见但成功提示占据主要视觉位置)。

7.4 查看历史

下方"反馈记录"区域出现刚提交的记录。分类标签为红色"问题反馈",右上角显示提交时间。再次点击"继续反馈",表单恢复,选择新分类"功能建议",提交第二条记录。历史区域新增一条蓝色标签的记录。

八、总结

本文通过"用户反馈与建议"这个实战案例,全面讲解了 ArkUI Select 和 TextArea 组件的组合使用。核心知识点包括:

  1. Select 组件:SelectOption 数组、selected/value 同步、onSelect 回调、选项样式
  2. TextArea 组件:text 绑定、placeholder 提示、onChange 实时监听、字数统计
  3. 表单验证:canSubmit 最低要求、按钮动态激活/禁用
  4. 提交与重置:一次提交 → 成功提示 → 继续反馈的闭环流程
  5. 历史记录:slice + concat 新数组引用、分类彩色标签、时间标注
  6. Font 类型陷阱:color 不属于 Font 对象,需用 fontColor() 单独设置

Select + TextArea + TextInput 的组合是移动端表单开发的"黄金三角"——Select 负责分类选择(限定输入域),TextArea 负责长文输入(开放输入域),TextInput 负责短文输入(结构化输入域)。三者各司其职,覆盖了表单输入的三个核心维度。


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐