4、ArkUI组件基础:Text、Image、Button、TextField等基础组件使用

好,咱们今天聊聊ArkUI里最常用的几个基础组件。说实话,这些组件看着简单,但用好了真能省不少事。我在做跨设备应用时,发现很多新手容易在基础组件上翻车——不是样式对不齐,就是事件处理出问题。咱们一个一个来拆解。

4.1 Text组件:不只是显示文字

Text组件,说白了就是用来展示文本的。但你别小看它,ArkUI的Text组件比你想的要强大。

核心用法:

Text('Hello, HarmonyOS!')
  .fontSize(20)
  .fontColor(Color.Blue)
  .fontWeight(FontWeight.Bold)
  .textAlign(TextAlign.Center)
  .lineHeight(30)
  .maxLines(2)
  .textOverflow({ overflow: TextOverflow.Ellipsis })

嗯,这里要注意几个点。我在项目中遇到过一个问题:多行文本截断时,如果不设置maxLinestextOverflow,文字会直接溢出容器。你想想看,在手机屏幕上还好,但到了平板上,布局一变,文字就乱跑了。

我的习惯:只要文本长度不确定,我一定会加上maxLinestextOverflow。这是防坑的基本操作。

另外,Text组件支持富文本样式。你可以用Span子组件实现不同颜色的文字混排:

Text() {
  Span('这是红色')
    .fontColor(Color.Red)
    .fontSize(16)
  Span('这是蓝色')
    .fontColor(Color.Blue)
    .fontSize(18)
  Span('这是加粗')
    .fontWeight(FontWeight.Bold)
}

为什么会这样设计?因为ArkUI的Text组件实际上是一个容器,可以容纳多个Span。这在做关键词高亮、价格标签时特别有用。

4.2 Image组件:图片加载的那些坑

Image组件,每个应用都离不开。但我敢说,90%的开发者都踩过图片加载的坑。

我曾经犯过的错:直接加载大图不做压缩,结果在低端设备上直接OOM。后来我学乖了,一定要设置objectFit和图片尺寸。

Image($r('app.media.icon'))
  .width(100)
  .height(100)
  .objectFit(ImageFit.Cover)
  .borderRadius(10)
  .alt('加载失败')

这里有几个关键属性:

属性 作用 推荐值
objectFit 图片缩放模式 Cover(裁剪填充)或 Contain(完整显示)
alt 加载失败时的替代文本 必填,提升用户体验
borderRadius 圆角 根据设计稿来

我个人习惯用ImageFit.Cover,因为它能保证图片填满容器,不会出现白边。但要注意,如果图片主体内容在边缘,Cover模式可能会裁掉重要信息。这时候就得用Contain了。

还有一点,ArkUI支持网络图片:

Image('https://example.com/logo.png')
  .width(200)
  .height(100)

嗯,这里要提醒你:网络图片一定要做缓存处理。我在项目中遇到过,每次页面刷新都重新下载图片,流量消耗巨大。后来用了ImageCache策略才解决。

4.3 Button组件:交互的起点

Button是用户交互的核心。ArkUI的Button组件支持多种样式,但很多人只会用默认的。

Button('点击我')
  .type(ButtonType.Capsule)
  .backgroundColor('#007AFF')
  .fontColor(Color.White)
  .fontSize(16)
  .width(200)
  .height(48)
  .onClick(() => {
    console.info('按钮被点击了')
  })

ButtonType有三种:

  • Capsule:胶囊样式,圆角最大,适合主要操作
  • Circle:圆形,适合图标按钮
  • Normal:普通矩形,适合次要操作

避坑指南:我曾经把登录按钮设成Normal样式,结果用户反馈说「这按钮看着不像能点的」。后来改成Capsule样式,点击率直接提升了30%。你想想看,视觉反馈对用户体验有多重要。

另外,按钮的禁用状态也要处理好:

Button('提交')
  .enabled(this.isFormValid)
  .backgroundColor(this.isFormValid ? '#007AFF' : '#CCCCCC')

嗯,这里要注意:禁用时不仅要改变颜色,最好也改变光标样式或透明度,让用户一眼就能看出「这个按钮现在点不了」。

4.4 TextField组件:输入框的细节

TextField,也就是输入框。这个组件看似简单,但细节特别多。我在做表单页面时,几乎每次都要调半天。

TextField({ placeholder: '请输入用户名' })
  .width('100%')
  .height(48)
  .backgroundColor('#F5F5F5')
  .borderRadius(8)
  .padding({ left: 16 })
  .fontSize(16)
  .onChange((value: string) => {
    this.username = value
  })

关键属性一览:

属性 说明 示例
placeholder 占位提示文字 '请输入手机号'
type 输入类型 InputType.Password(密码)
maxLength 最大字符数 11
showPasswordIcon 密码可见切换 true

我曾经踩过的坑:密码输入框忘记设置type: InputType.Password,结果用户输入的密码明文显示在屏幕上。这要是被旁边的人看到,后果不堪设想。所以,密码框一定要显式声明类型。

还有,输入框的键盘类型也很重要:

TextField({ placeholder: '请输入手机号' })
  .type(InputType.Number)  // 数字键盘
  .maxLength(11)

为什么这么做?因为手机号只需要数字,弹出全键盘会让用户多一步切换操作。你想想看,每次多一步操作,100个用户就是100步,体验差距就出来了。

4.5 组件组合实战:一个登录表单

好了,咱们把上面这些组件串起来,做一个简单的登录表单。这是我个人很喜欢的练习方式——把零散的知识点组合成一个完整功能。

@Entry
@Component
struct LoginPage {
  @State username: string = ''
  @State password: string = ''
  @State isLoginEnabled: boolean = false

  build() {
    Column() {
      // 标题
      Text('欢迎登录')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 40 })

      // 用户名输入框
      TextField({ placeholder: '请输入用户名' })
        .width('80%')
        .height(48)
        .backgroundColor('#F5F5F5')
        .borderRadius(8)
        .padding({ left: 16 })
        .onChange((value) => {
          this.username = value
          this.checkLoginEnabled()
        })

      // 密码输入框
      TextField({ placeholder: '请输入密码' })
        .width('80%')
        .height(48)
        .backgroundColor('#F5F5F5')
        .borderRadius(8)
        .padding({ left: 16 })
        .margin({ top: 16 })
        .type(InputType.Password)
        .showPasswordIcon(true)
        .onChange((value) => {
          this.password = value
          this.checkLoginEnabled()
        })

      // 登录按钮
      Button('登录')
        .width('80%')
        .height(48)
        .backgroundColor(this.isLoginEnabled ? '#007AFF' : '#CCCCCC')
        .fontColor(Color.White)
        .borderRadius(24)
        .margin({ top: 32 })
        .enabled(this.isLoginEnabled)
        .onClick(() => {
          console.info('登录成功')
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  checkLoginEnabled() {
    this.isLoginEnabled = this.username.length > 0 && this.password.length > 0
  }
}

我的建议:表单验证逻辑一定要写在独立的函数里,比如checkLoginEnabled。这样代码清晰,也方便后续扩展——比如加个「密码必须8位以上」的规则,直接改这个函数就行。

嗯,到这里,ArkUI的基础组件就讲完了。Text、Image、Button、TextField这四个组件,几乎覆盖了90%的UI场景。你只要把它们用熟了,大部分页面都能快速搭建出来。

我记得刚开始学ArkUI时,总觉得组件太多记不住。后来发现,其实每个组件就那么几个核心属性——尺寸、颜色、事件。抓住这三点,其他都是锦上添花。

下一章咱们聊聊布局组件,到时候你会看到,这些基础组件是怎么在Flex、Column、Row里排兵布阵的。