基础内容可参考
对焦框坐标基本概念:
Android Camera2之 手动点击区域对焦 - 简书
CSDN
Camera2点击对焦实现 - mydddfly - 博客园
本文主要总结自己开发过程中遇到的各个知识点
需求: Camera2? App开发:取消自动对焦,设置为触摸手动对焦,对焦完成后依然不允许自动对焦
思路:
触摸屏幕OnTouchListener监听--》根据坐标转换,计算对焦区域--》进行对焦--》显示对焦框
1、触摸屏幕,
private View.OnTouchListener mOntouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
try {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
int[] location = new int[2];
mTextureView[0].getLocationOnScreen(location);
int tmpx = mTextureView[0].getWidth();
int tmpy = mTextureView[0].getHeight();
Log.d(TAG, "onTouch,TextureView.getWidth:" + tmpx +
",TextureView.getHeight:" + tmpy + ",location[0]:" + location[0] +
",location[1]" + location[1] + ",TextureView.getLeft:" + mTextureView[0].getLeft()
+ ",TextureView.getTop:" + mTextureView[0].getTop()+", mTextureView[0].getRight():"+ mTextureView[0].getRight()+", mTextureView[0].getBottom():"+ mTextureView[0].getBottom());
int focusWidth = mAutoFoucView.getLayoutParams().width;
int focusHeight = mAutoFoucView.getLayoutParams().height;
float x_raw = event.getRawX();//between screen
float y_raw = event.getRawY();//between screen
mAutoFoucView.setVisibility(View.VISIBLE);
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mAutoFoucView.getLayoutParams();
// int left = (int) (event.getX() - focusWidth / 2 + location[0]);
// int top = (int) (event.getY() - focusHeight / 2 + location[1]);
int left = (int) (event.getX() - focusWidth / 2);
int top = (int) (event.getY() - focusHeight / 2);
Log.d(TAG, "onTouch,focusWidth:" + focusWidth +
",focusHeight:" + focusHeight + ",event.getX():" + event.getX() +
",event.getY():" + event.getY() + ",event.getRawX():" + event.getRawX()
+ ",event.getRawY():" + event.getRawY());
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
mAutoFoucView.setLayoutParams(layoutParams);
mAutoFoucView.prepareFocus();
int width = mTextureView[0].getWidth();
int height = mTextureView[0].getHeight();
meteringRectangle = getMeteringRectangles(event.getX(), event.getY(), width, height);
Message msg = Message.obtain();
msg.what = CameraOpt.MSG_SET_TOUCH_POINT_VALUE;
msg.obj= meteringRectangle;
msg.arg1 = mAutoFoucView.isFocusing()? 1 : 0;
mCameraOpt[0].getHandler().sendMessage(msg);
break;
}
return true;
} catch (Exception e) {
Log.v("onTouch", e.toString());
return false;
}
}
};
case MSG_SET_TOUCH_POINT_VALUE:
meteringRectangle =(MeteringRectangle[]) msg.obj;
isFocusing = msg.arg1 != 0;
//Log.i(TAG,"isFocusing="+isFocusing);
onTouchFoucs(meteringRectangle);
break;
private void onTouchFoucs(MeteringRectangle[] meteringRectangle) {
if(isFocusing)
{
//设置AF/AE对焦区域,开始对焦
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, meteringRectangle);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, meteringRectangle);
// mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
mPreviewRequest = mPreviewRequestBuilder.build();
try {
mCaptureSession.setRepeatingRequest(mPreviewRequest, mPreviewListener, mHandler);
} catch (CameraAccessException e) {
Log.e(TAG, "setRepeatingRequest failed, " + e.getMessage());
}
}
}
private final CameraCaptureSession.CaptureCallback mPreviewListener = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
Log.d(TAG, "onCaptureCompleted begin isFocusing="+isFocusing);
if (mPreviewRequestBuilder == null) {
return;
}
if(isFocusing){
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);//
Log.d(TAG, "onCaptureCompleted begin afState="+afState);
if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
|| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
isFocusSucess = true;
mCamLister.onFocusState(isFocusSucess);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
//如果对焦完成后不允许自动对焦,注释掉如下几行。
// mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
// mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
mPreviewRequest = mPreviewRequestBuilder.build();
try {
mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mHandler);//
} catch (CameraAccessException e) {
Log.e(TAG, "setRepeatingRequest failed, errMsg: " + e.getMessage());
}
}
else {
isFocusSucess = false;
mCamLister.onFocusState(isFocusSucess);
}
}
isFocusing = false;
super.onCaptureCompleted(session, request, result);
// Log.d(TAG, mCameraId + " onCaptureCompleted end");
}
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
@Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
super.onCaptureFailed(session, request, failure);
}
};
mPreviewListener是监听预览界面;
getMeteringRectangles函数后面补充
|