鸿蒙相机开发中篇:自定义 UI 与拍摄控制

鸿蒙相机开发中篇:自定义 UI 与拍摄控制

------ 前后摄像头切换、点击对焦、曝光控制与动画动效


一、前言

上一篇《鸿蒙相机开发入门篇》中,我们完成了一个最小可用的相机应用,能实现预览与拍照。

但真正的相机 App 不只是能"拍",还要有流畅的交互体验,比如:

  • 自定义取景框
  • 切换前后摄像头
  • 点击自动对焦
  • 曝光补偿与预览动画

本篇将继续基于 @ohos.multimedia.camera 模块,带你逐步构建一个带交互控制与动效的相机 UI。


二、核心知识点回顾

功能 使用类 说明
前后摄像头切换 CameraManager.getSupportedCameras() 返回多个可用摄像头,通常索引 0 是后置,1 是前置
对焦控制 CameraInput.setFocusMode() / CameraInput.setFocusPoint() 设置自动/手动对焦点
曝光补偿 CameraInput.setExposureBias() 调节亮度
动画动效 ArkUI 动画系统 (.animation) 提供平滑的过渡和点击反馈

三、自定义取景框与 UI 布局

我们使用一个半透明取景框 + 工具栏布局:

typescript 复制代码
// pages/CustomCameraPage.ets
import camera from '@ohos.multimedia.camera';
import { prompt } from '@kit.ArkUI';

@Entry
@Component
struct CustomCameraPage {
  @State isFront: boolean = false;
  @State focusX: number = 0;
  @State focusY: number = 0;
  controller: camera.CameraManager = camera.getCameraManager(globalThis.context);
  session?: camera.Session;
  cameraInput?: camera.CameraInput;
  previewOutput?: camera.PreviewOutput;
  photoOutput?: camera.PhotoOutput;

  build() {
    Stack() {
      // 相机预览区域
      XComponent({ id: 'cameraPreview', type: XComponentType.SURFACE })
        .onLoad((context) => this.initCamera(context))
        .width('100%')
        .height('100%')
        .onTouch((event) => this.handleFocus(event)) // 点击对焦
      // 取景框遮罩
      Rect()
        .width('80%')
        .height('60%')
        .border({ width: 2, color: '#FFFFFF' })
        .opacity(0.5)
        .align(Alignment.Center)

      // 对焦点动画
      if (this.focusX !== 0) {
        Image($r('app.media.focus_ring'))
          .width(40)
          .height(40)
          .position({ x: this.focusX - 20, y: this.focusY - 20 })
          .animation({ duration: 300, curve: Curve.EaseOut })
      }

      // 底部工具栏
      Column({ space: 20 }) {
        Button(this.isFront ? '切换后摄' : '切换前摄')
          .onClick(() => this.switchCamera())
          .width(160).height(50)
          .backgroundColor('#444').fontColor('#fff').borderRadius(25)

        Button('拍照')
          .onClick(() => this.takePhoto())
          .width(100).height(100)
          .borderRadius(50)
          .backgroundColor('#007DFF')
      }
      .align(Alignment.BottomCenter)
      .padding(20)
    }
  }

四、前后摄像头切换逻辑

kotlin 复制代码
async initCamera(context) {
  const cameras = this.controller.getSupportedCameras();
  const selected = cameras[this.isFront ? 1 : 0];
  this.cameraInput = this.controller.createCameraInput(selected);
  this.previewOutput = this.controller.createPreviewOutput(context);
  this.photoOutput = this.controller.createPhotoOutput();

  this.session = this.controller.createSession(camera.SessionType.SESSION_TYPE_NORMAL);
  await this.session.beginConfig();
  this.session.addInput(this.cameraInput);
  this.session.addOutput(this.previewOutput);
  this.session.addOutput(this.photoOutput);
  await this.session.commitConfig();
  await this.cameraInput.open();
  this.previewOutput.start();
}

async switchCamera() {
  this.isFront = !this.isFront;
  await this.session?.stop();
  await this.cameraInput?.close();
  await this.initCamera(globalThis.context);
}

五、点击自动对焦

ini 复制代码
handleFocus(event) {
  const point = event.touches[0];
  this.focusX = point.x;
  this.focusY = point.y;

  if (this.cameraInput) {
    this.cameraInput.setFocusMode(camera.FocusMode.AUTO);
    this.cameraInput.setFocusPoint({ x: point.x, y: point.y });
  }

  setTimeout(() => {
    this.focusX = 0; // 动画结束隐藏
    this.focusY = 0;
  }, 800);
}

🔍 说明

  • setFocusMode() 可切换到自动或手动对焦。
  • 坐标点是基于 XComponent 的触摸事件。
  • 通过短暂显示对焦圆环动画反馈用户操作。

六、增加曝光调节

scss 复制代码
Slider({ value: 0, min: -1, max: 1, step: 0.1 })
  .onChange((value) => {
    if (this.cameraInput) {
      this.cameraInput.setExposureBias(value);
    }
  })
  .width('60%')
  .align(Alignment.BottomCenter)
  .margin({ bottom: 80 })

🌞 曝光值范围通常为 -1, 1,可以根据光线场景动态调整。


七、小结与下一篇预告

到这里,我们已经实现了:

✅ 前后摄像头切换

✅ 点击自动对焦

✅ 曝光调节

✅ 自定义 UI 与对焦动效

下一篇(下篇:相机动效与性能优化)我们将继续探讨:

  • 相机启动/恢复动画
  • 快门和聚焦动效
  • 在 Worker 线程中使用相机(性能优化)
  • HDR、Vivid、高帧率预览
相关推荐
byte轻骑兵2 小时前
2026手机远程办公:向日葵、TeamViewer、ToDesk鸿蒙适配+传文件+AI审计功能对比
智能手机·harmonyos·todesk·teamviewer·手机远程办公
贾伟康3 小时前
【知律|06】HarmonyOS ArkTS 法律分类实战:让民法、劳动、消费等入口可维护
harmonyos·arkts·arkui·分类设计·多设备
梦想不只是梦与想17 小时前
鸿蒙 测试工具:DevEco Testing(一)
测试工具·harmonyos·testing
大锅盖120 小时前
Web 工单要调用相机,第一步不是打开取景框,而是建立能力门禁
前端·数码相机·harmonyos
贾伟康1 天前
【华夏二十四节气|07】HarmonyOS 6.0.2(22) ArkTS 节气搜索实战:多字段匹配与四态闭环
移动开发·harmonyos·arkts·arkui·本地搜索
大龄秃头程序员1 天前
Flutter 项目鸿蒙适配实战:从环境搭建到多环境打包全指南
harmonyos
贾伟康1 天前
【万能转换器|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致
移动开发·harmonyos·arkts·权限管理·隐私合规
贾伟康1 天前
【万能转换器|19】HarmonyOS ArkTS 回归测试实战:覆盖启动、空数据、异常输入和重复点击
软件测试·移动开发·harmonyos·arkts·回归测试
UnicornIT1 天前
【HarmonyOS】时间管理类APP:做成“自适应“
ui·华为·harmonyos·鸿蒙
less_121381 天前
HarmonyOS WPS Open SDK:不落地、水印与功能开关的合规打开策略
华为·harmonyos·wps