Android自定义View实现相机对焦框

Nyako ·
更新时间:2024-09-20
· 1765 次阅读

前言

在相机APP中,手动对焦时都会出现一个对焦框,告诉用户相机正在对焦。那么这种对焦框是怎么实现的呢?
最近项目中有几个需求,实现手动对焦,自动对焦和对焦框。总体来说不是很复杂,在这片文章中我简单介绍一下。

效果展示

对焦框:

对焦框是用自定义view实现的,实现方法还是和以前一样,继承View类,重载构造方法,初始化画笔,在onTouchEvent里面获取当前点击位置的x y轴坐标,在onDraw方法里面调用canvas的drawCircle方法,把我门刚才记录下来的x y轴坐标,半径,画笔等参数传给drawCircle方法就可以画出对焦框了。

点击事件:

如果在外部直接调用view的setOnclickListener方法是获取不到点击事件的,所以点击事件需要使用interface来实现,在外部实现ClickEvent这个接口就可以获取到view的点击事件了。

interface ClickEvent {          fun clicked()     } private var clickEvent: ClickEvent? = null  fun setClickEvent(clickEvent: ClickEvent) {         this.clickEvent = clickEvent     }

因为相机app刚打开时,对焦框是不可见的,所以我把默认颜色设置成透明色。当view点击时才会显示出来,这里就修改paint的颜色为白色即可。然后对焦完成后把对焦框隐藏掉,把对焦框颜色设置为透明。

其实还有一种方法是可以使用view的visibility属性,调用invisible或gone方法。但是当你修改view的显示状态时会间接地调用invalidate方法,随后onDraw方法就会被调用。我们在onDraw方法里面传递的x y坐标是全局变量,所以每次调用invisible/visible方法会调用onDraw方法,这里传进去的x y坐标是我们上一次点击位置,所以当你点击屏幕时对焦框的位置是不对的,有可能是显示在上次点击的那个位置上。为了避免这种情况就用了改变颜色的方式。

完整代码 import android.annotation.SuppressLint import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.util.AttributeSet import android.view.MotionEvent import android.view.View class CircleView@JvmOverloads constructor(     context: Context,     attrs: AttributeSet? = null,     defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr){     interface ClickEvent {          fun clicked()     }     private var clickEvent: ClickEvent? = null     fun setClickEvent(clickEvent: ClickEvent) {         this.clickEvent = clickEvent     }     private val paint: Paint     private val radius = 80f     private var currentX = 0.0f     private var currentY = 0.0f     init {         paint = Paint()         paint.color = Color.TRANSPARENT         paint.style = Paint.Style.STROKE         paint.strokeWidth = 4f     }     override fun onDraw(canvas: Canvas?) {         super.onDraw(canvas)         canvas?.drawCircle(currentX, currentY, radius, paint)     }     @SuppressLint("ClickableViewAccessibility")     override fun onTouchEvent(event: MotionEvent?): Boolean {         when (event?.action) {             MotionEvent.ACTION_DOWN -> {                 currentX = event.x                 currentY = event.y                 paint.color = Color.WHITE                 clickEvent?.clicked()                 invalidate()             }         }         return true     }     fun invisible(){         paint.color = Color.TRANSPARENT         invalidate()     } }

xml代码

<com.example.camera.CircleView         android:id="@+id/circle"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:layout_gravity="center"> </com.example.camera.CircleView>

Main Activity

private var myAutoFocusCallback : Camera.AutoFocusCallback? = null     private fun focusListener(){         myAutoFocusCallback = Camera.AutoFocusCallback {isFocused , _ ->             if (isFocused) {                 Log.d("test", "对焦成功")                 circle.invisible()                 showToast("对焦成功")             } else {                 Log.d("test", "对焦失败")             }         }     }     private fun getFocus() {         Log.d("test", "正在对焦")         camera?.autoFocus(myAutoFocusCallback)     }     override fun clicked() {         getFocus()     }

这里简单介绍介绍一下对焦功能的实现方法:

核心代码是camera的autoFocus方法。

手动对焦:每次点击surface时可以调用camera的autoFocus方法进行对焦。

如果想要实现自动对焦功能,可以借助计时器,比如每隔200毫秒校准一次,校准完成后关闭计时器等。



view 相机 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号