I'm working on an app which has a custom camera screen, for which I'm supposed to implement tap to focus, like in the Android(more specifically, the Galaxy S4) camera app.
I've tried using the steps outlined here, but it doesn't seem to cause any noticeable focusing. The Focus Mode is set to Continuous Picture(we are supporting only a specific device).
When the user taps on the camera preview, I need to be focusing on the top half of the image. For this, I use the code snippet
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); }
I do NOT want AutoFocus as it takes too long to focus on the image. I am interested only in the top half of the image. Has anybody successfully implemented Tap to Focus along with Continuous Picture mode?
And with a smartphone camera it couldn't be simpler to do. Using the built-in camera app on either an Android device (running 4.0 or later) or a recent iPhone, just tap the screen to specify where the camera should acquire focus. An autofocus square will appear for a moment onscreen at the location you tapped.
Make sure the camera is set to manual focus. Zoom in as tight as you can on the subject you wish to focus on. Adjust the focus ring until the picture is sharp. Turn the ring clockwise for closer focus, anti-clockwise for more distant focus.
Flip the switch on your lens to "MF." Check the side of your DSLR (digital single-lens reflex) or SLR lens for a small switch labeled "AF - MF" or "A - M." If the switch is set to "AF," or automatic focus," flip it to "MF," or manual focus.
Bumped into this issue recently. As MatheusJardimB said, this question helps a lot.
However, in my case, I wanted to start in the ContinuousPicture
mode then be able to tap to focus and then continue with the ContinuousPicture
mode.
I managed to get it to work by using the onAutoFocus
method of the Camera.AutoFocusCallback()
. I'm not sure if it's the best or the prettiest way of doing it, but it seems to work.
Here's the code:
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; });
You could just change the focus area to
ArrayList<Area> focusAreas = new ArrayList<Camera.Area>(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750));
and it should work.
UPDATE
I recently acquired a Samsung S5 and tested this out on it. It didn't work that well, so I added a few modifications and it's working now. This was also successfully tested on the Galaxy S6 and Galaxy Note4.
Here's the modified code:
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; } });
this has the solution. I just added the implementation of some missing methods in his code.
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; }
// implement this callback to trigger the focus.
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!"); } } };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With