什么是实现点击对焦相机的正确方法?

我正在开发一个应用程序,该应用程序具有自定义相机屏幕,为此我应该实现点按式对焦,就像在Android(更具体地说,Galaxy S4)相机应用程序中一样。

我试过使用这里列出的步骤,但似乎没有引起任何明显的重点。 对焦模式设置为连拍(仅支持特定设备)。

当用户点击相机预览时,我需要关注图像的上半部分。 为此,我使用代码片段

Parameters parameters = mCamera.getParameters(); if (parameters.getMaxNumFocusAreas() > 0) { ArrayList<Area> focusAreas = new ArrayList<Camera.Area>(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750)); parameters.setFocusAreas(focusAreas); mCamera.setParameters(parameters); } 

我不想要自动对焦,因为它需要太长的时间来专注于图像。 我只对图像的上半部分感兴趣。 有没有人成功实现了轻拍焦点和连续图片模式?

最近碰到这个问题。 正如MatheusJardimB所说, 这个问题有很大帮助。

不过,就我而言,我想从ContinuousPicture模式开始,然后点击进行对焦,然后继续进行ContinuousPicture模式。

我设法通过使用Camera.AutoFocusCallback()onAutoFocus方法得到它的工作。 我不确定这是否是最好的或最漂亮的方式,但它似乎工作。

代码如下:

 setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mCamera != null) { Camera camera = mCamera.getCamera(); camera.cancelAutoFocus(); Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f); Parameters parameters = camera.getParameters(); parameters.setFocusMode(Parameters.FOCUS_MODE_MACRO); if (parameters.getMaxNumFocusAreas() > 0) { List<Area> mylist = new ArrayList<Area>(); mylist.add(new Camera.Area(focusRect, 1000)); parameters.setFocusAreas(mylist); } camera.setParameters(parameters); camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { camera.cancelAutoFocus(); Parameters params = camera.getParameters(); if (params.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(params); } } }); } return true; } return false; }); 

您可以将焦点区域更改为

 ArrayList<Area> focusAreas = new ArrayList<Camera.Area>(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750)); 

它应该工作。

UPDATE

我最近收购了三星S5,并对此进行了testing。 它不能很好地工作,所以我添加了一些修改,现在正在工作。 这也成功地在Galaxy S6和Galaxy Note4上进行了testing。

这是修改的代码:

 setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mCamera != null) { Camera camera = mCamera.getCamera(); camera.cancelAutoFocus(); Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f); Parameters parameters = camera.getParameters(); if (parameters.getFocusMode().equals( Camera.Parameters.FOCUS_MODE_AUTO) { parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); } if (parameters.getMaxNumFocusAreas() > 0) { List<Area> mylist = new ArrayList<Area>(); mylist.add(new Camera.Area(focusRect, 1000)); parameters.setFocusAreas(mylist); } try { camera.cancelAutoFocus(); camera.setParameters(parameters); camera.startPreview(); camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (camera.getParameters().getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { Parameters parameters = camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); if (parameters.getMaxNumFocusAreas() > 0) { parameters.setFocusAreas(null); } camera.setParameters(parameters); camera.startPreview(); } } }); } catch (Exception e) { e.printStackTrace(); } } return true; } }); 

这有解决办法。 我只是在他的代码中添加了一些缺less的方法的实现。

 private static final int FOCUS_AREA_SIZE= 300; 

//

 mCameraPreview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { focusOnTouch(event); } return true; } }); 

//

  private void focusOnTouch(MotionEvent event) { if (mCamera != null ) { Camera.Parameters parameters = mCamera.getParameters(); if (parameters.getMaxNumMeteringAreas() > 0){ Log.i(TAG,"fancy !"); Rect rect = calculateFocusArea(event.getX(), event.getY()); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); meteringAreas.add(new Camera.Area(rect, 800)); parameters.setFocusAreas(meteringAreas); mCamera.setParameters(parameters); mCamera.autoFocus(mAutoFocusTakePictureCallback); }else { mCamera.autoFocus(mAutoFocusTakePictureCallback); } } } private Rect calculateFocusArea(float x, float y) { int left = clamp(Float.valueOf((x / mCameraPreview.getWidth()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE); int top = clamp(Float.valueOf((y / mCameraPreview.getHeight()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE); return new Rect(left, top, left + FOCUS_AREA_SIZE, top + FOCUS_AREA_SIZE); } private int clamp(int touchCoordinateInCameraReper, int focusAreaSize) { int result; if (Math.abs(touchCoordinateInCameraReper)+focusAreaSize/2>1000){ if (touchCoordinateInCameraReper>0){ result = 1000 - focusAreaSize/2; } else { result = -1000 + focusAreaSize/2; } } else{ result = touchCoordinateInCameraReper - focusAreaSize/2; } return result; } 

//实现这个callback触发焦点。

 private Camera.AutoFocusCallback mAutoFocusTakePictureCallback = new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { // do something... Log.i("tap_to_focus","success!"); } else { // do something... Log.i("tap_to_focus","fail!"); } } }; 

其他答案之一会导致你的相机放弃之前给出的重点,并返回到连续的焦点,我不认为是有道理的。

另外,如果你看看post中的链接,原来的答案使用parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

我已经用这行代码而不是连续的焦点实现了上述,它似乎工作得更好。

我有同样的问题。 我已经检查了很多设备,以及许多Android版本。

看来聚焦区域在连续聚焦模式下不起作用

我的解决方法是将焦点模式设置为AUTO或MACRO以及设置焦点区域:

 params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO); params.setFocusAreas(focusAreas); mCamera.setParameters(params); 

请注意,Galaxy S3和S4上的相机应用程序的工作方式是相同的:它永久处于连续模式。 当您触摸屏幕时,它会切换到自动并设置对焦区域。 但过了一段时间,它会回到连续模式,焦点区域会回到屏幕中央。

我希望这能帮助你。