鸿蒙相机开发中篇:自定义 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、高帧率预览
相关推荐
鸿蒙小白龙9 小时前
OpenHarmony 与 HarmonyOS 的 NAPI 开发实战对比:自上而下与自下而上的差异解析
harmonyos·鸿蒙·鸿蒙系统·open harmony
喵手10 小时前
【参赛心得】从“碰一碰”到“服务流转”:HarmonyOS创新赛金奖作品“智游文博”全流程复盘!
华为·harmonyos·鸿蒙应用开发·1024征文
鸿蒙小白龙10 小时前
OpenHarmony平台大语言模型本地推理:llama深度适配与部署技术详解
人工智能·语言模型·harmonyos·鸿蒙·鸿蒙系统·llama·open harmony
安卓开发者10 小时前
鸿蒙NEXT Wear Engine开发实战:手机侧应用如何调用穿戴设备能力
华为·智能手机·harmonyos
Damon小智11 小时前
仓颉 Markdown 解析库在 HarmonyOS 应用中的实践
华为·typescript·harmonyos·markdown·三方库
ZIM学编程12 小时前
把握鸿蒙生态红利:HarmonyOS 应用开发学习路径与实战课程推荐
学习·华为·harmonyos
安卓开发者1 天前
鸿蒙NEXT应用接入快捷栏:一键直达,提升用户体验
java·harmonyos·ux
HMS Core1 天前
消息推送策略:如何在营销与用户体验间找到最佳平衡点
华为·harmonyos·ux
Brianna Home1 天前
【案例实战】鸿蒙分布式调度:跨设备协同实战
华为·wpf·harmonyos