Каков правильный способ применения Tap To Focus для камеры?

Я работаю над приложением, у которого есть пользовательский экран камеры, для которого я должен использовать краткий фокус, например, в приложении для 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); } 

Я НЕ хочу, чтобы AutoFocus занимал слишком много времени, чтобы сфокусироваться на изображении. Меня интересует только верхняя половина изображения. Кто-нибудь успешно реализовал Tap to Focus вместе с режимом непрерывной съемки?

В последнее время это произошло. Как сказал MatheusJardimB, этот вопрос очень помогает.

Тем не менее, в моем случае, я хотел начать в режиме ContinuousPicture затем нажать, чтобы сфокусироваться, а затем продолжить режим ContinuousPicture .

Мне удалось заставить его работать, используя метод onAutoFocus для Camera.AutoFocusCallback() . Я не уверен, что это лучший или самый красивый способ сделать это, но, похоже, он работает.

Вот код:

 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)); 

И он должен работать.

ОБНОВИТЬ

Недавно я приобрел Samsung S5 и протестировал его на нем. Это не сработало, поэтому я добавил несколько изменений и теперь работает. Это также было успешно протестировано на Galaxy S6 и Galaxy Note4.

Вот модифицированный код:

 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; } }); 

Это решение. Я просто добавил реализацию некоторых недостающих методов в своем коде.

 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; } 

// реализуем этот обратный вызов для запуска фокуса.

 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!"); } } }; получится 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!"); } } }; 

Один из других ответов заставляет камеру отбрасывать ранее заданные точки фокусировки и возвращаться к непрерывному фокусу, который, как мне кажется, не имеет смысла.

Также, если вы посмотрите на ссылку в сообщении, исходный ответ использует параметры.setFocusMode (Parameters.FOCUS_MODE_AUTO);

Я реализовал выше с этой строкой кода вместо непрерывного фокуса, и, похоже, он работает намного лучше.

У меня такая же проблема. Я проверил это на многих устройствах и на многих версиях Android.

Похоже, что фокус-область не работает в режиме непрерывного фокуса .

Мое обходное решение – установить режим фокусировки на AUTO или MACRO вместе с настройкой фокуса:

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

Обратите внимание, что приложение Camera Camera на Galaxy S3 & S4 работает одинаково: оно постоянно в непрерывном режиме. Когда вы касаетесь экрана, он переключается на авто и устанавливает область фокусировки. Но через некоторое время он возвращается в непрерывный режим, а фокус-область возвращается в центр экрана.

Надеюсь, вам это поможет.