I am trying to do zoom using double finger touch gesture in the camera preview mode. But i unable to do that. I have done that Zoom control on the ImageView and it\'s working fi
I got the solution of my problem, Following is the solution.
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM) {
float newDist = spacing(event);
double zoomDist = newDist-oldDist;
if(zoomDist > 0){
if(zoomDist > 50 && zoomDist <= 200){
if (curZoomLevel < mZoomMax && gestureZoom == 0) {
gestureZoom ++;
GestureZoomIn();
}
}else if(zoomDist > 200 && zoomDist <= 300){
if (curZoomLevel < mZoomMax && gestureZoom == 1) {
gestureZoom ++;
GestureZoomIn();
}
}else if(zoomDist > 300 && zoomDist <= 400){
if (curZoomLevel < mZoomMax && gestureZoom == 2) {
gestureZoom++;
GestureZoomIn();
}
//
private void GestureZoomIn(){
if (mParameters.isZoomSupported()){
mZoomMax = mParameters.getMaxZoom();
if (zoom_text_value<mZoomMax) {
zoom_text_value++;
curZoomLevel++;
zoom_float=zoom_float+0.5;
onZoomValueChanged(curZoomLevel);
//
private void GestureZoomOut(){
if (mParameters.isZoomSupported()){
if (0<zoom_text_value) {
zoom_text_value--;
curZoomLevel--;
zoom_float=zoom_float-0.5;
onZoomValueChanged(curZoomLevel);
The above code i used to implement the multi zoom in camera review.
Here is a solution I found on github: https://github.com/Betulaphobe/ChatCapsule/blob/8d4f00a7d4c9166aa7ce974670fdf3033a6064f4/chc_application/src/chc/helpers/CameraPreview.java
@Override
public boolean onTouchEvent(MotionEvent event) {
// Get the pointer ID
Camera.Parameters params = mCamera.getParameters();
int action = event.getAction();
if (event.getPointerCount() > 1) {
// handle multi-touch events
if (action == MotionEvent.ACTION_POINTER_DOWN) {
mDist = getFingerSpacing(event);
} else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
mCamera.cancelAutoFocus();
handleZoom(event, params);
}
} else {
// handle single touch events
if (action == MotionEvent.ACTION_UP) {
handleFocus(event, params);
}
}
return true;
}
private void handleZoom(MotionEvent event, Camera.Parameters params) {
int maxZoom = params.getMaxZoom();
int zoom = params.getZoom();
float newDist = getFingerSpacing(event);
if (newDist > mDist) {
//zoom in
if (zoom < maxZoom)
zoom++;
} else if (newDist < mDist) {
//zoom out
if (zoom > 0)
zoom--;
}
mDist = newDist;
params.setZoom(zoom);
mCamera.setParameters(params);
}
public void handleFocus(MotionEvent event, Camera.Parameters params) {
int pointerId = event.getPointerId(0);
int pointerIndex = event.findPointerIndex(pointerId);
// Get the pointer's current position
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean b, Camera camera) {
// currently set to auto-focus on single touch
}
});
}
}
/** Determine the space between the first two fingers */
private float getFingerSpacing(MotionEvent event) {
// ...
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
Take a look at my implementation. Support for both Camera APIs: camera and camera2. You can zoom by using double finger touch.
This is how I use the code on my Activities.
For camera API just:
private void setupZoomHandler(final Camera.Parameters parameters) {
if ( parameters.isZoomSupported() ) {
SimpleZoomHandlerBuilder.forView( mCameraPreview )
.setMaxZoom( parameters.getMaxZoom() )
.setZoomListener( new SimpleZoomHandler.IZoomHandlerListener() {
@Override
public void onZoomChanged(int newZoom) {
Camera.Parameters params = mCamera.getParameters();
params.setZoom( newZoom );
mCamera.setParameters( params );
}
} )
.build();
}
}
And for camera2 API just:
private void setupZoomHandler(CameraCharacteristics cameraCharacteristics) {
ActiveArrayZoomHandlerBuilder.forView( mTextureView )
.setActiveArraySize( cameraCharacteristics.get( CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE ) )
.setMaxZoom( cameraCharacteristics.get( CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM ) * 10 )
.setZoomListener( new ActiveArrayZoomHandler.IZoomHandlerListener() {
@Override
public void onZoomChanged(Rect zoom) {
mCaptureRequestBuilder.set( CaptureRequest.SCALER_CROP_REGION, zoom );
updatePreview();
}
} )
.build();
}
Here are the classes you need to zoom handling:
public abstract class AbstractZoomHandler implements View.OnTouchListener {
private static final int FINGER_SPACING_DELTA_FOR_ZOOM = 25;
private static final int FINGER_SPACING_ZOOM_INCREMENT = 5;
private static final float DEFAULT_ZOOM_HARDNESS = 0.4f;
private float lastFingerSpacingTime;
private float fingerSpacingBuffer;
protected int zoomLevel;
protected float zoomIncrement;
protected float maxZoom;
public AbstractZoomHandler(View touchableView) {
touchableView.setOnTouchListener( this );
this.lastFingerSpacingTime = 0;
this.fingerSpacingBuffer = 0;
this.zoomLevel = 1;
setZoomHardness( DEFAULT_ZOOM_HARDNESS );
}
public void setMaxZoom(float maxZoom) {
this.maxZoom = maxZoom;
}
public void setZoomHardness(float zoomHardness) {
this.zoomIncrement = Math.round( zoomHardness * FINGER_SPACING_ZOOM_INCREMENT );
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if ( !isPrepared() ) {
return true;
}
if ( event.getAction() == MotionEvent.ACTION_UP ) {
fingerSpacingBuffer = 0;
return true;
}
if ( isTwoFingersTouchEvent( event ) ) {
int newZoomLevel = performTwoFingersZoom( event );
recalculateZoom( newZoomLevel );
}
return true;
}
private boolean isTwoFingersTouchEvent(MotionEvent event) {
return event.getPointerCount() == 2;
}
private int performTwoFingersZoom(MotionEvent event) {
int newZoomLevel = zoomLevel;
float currentFingerSpacingTime = getFingerSpacing( event );
fingerSpacingBuffer += currentFingerSpacingTime - lastFingerSpacingTime;
if ( fingerSpacingBuffer >= FINGER_SPACING_DELTA_FOR_ZOOM && maxZoom > zoomLevel ) {
newZoomLevel += zoomIncrement;
fingerSpacingBuffer = 0;
} else if ( fingerSpacingBuffer <= -FINGER_SPACING_DELTA_FOR_ZOOM && zoomLevel > 1 ) {
newZoomLevel -= zoomIncrement;
;
fingerSpacingBuffer = 0;
}
lastFingerSpacingTime = currentFingerSpacingTime;
return newZoomLevel;
}
private void recalculateZoom(int newZoomLevel) {
if ( newZoomLevel == zoomLevel ||
newZoomLevel < 0 ||
newZoomLevel > maxZoom) {
return;
}
zoomLevel = newZoomLevel;
notifyZoomChanged( zoomLevel );
}
private float getFingerSpacing(MotionEvent event) {
float x = event.getX( 0 ) - event.getX( 1 );
float y = event.getY( 0 ) - event.getY( 1 );
return (float) Math.sqrt( x * x + y * y );
}
public abstract void notifyZoomChanged(int zoom);
public abstract boolean isPrepared();
}
For Camera:
public class SimpleZoomHandler extends AbstractZoomHandler {
private IZoomHandlerListener zoomHandlerListener;
SimpleZoomHandler(View touchableView) {
super( touchableView );
}
public void setZoomHandlerListener(IZoomHandlerListener zoomHandlerListener) {
this.zoomHandlerListener = zoomHandlerListener;
}
@Override
public void notifyZoomChanged(int zoom) {
zoomHandlerListener.onZoomChanged( zoom );
}
@Override
public boolean isPrepared() {
return zoomHandlerListener != null;
}
public interface IZoomHandlerListener {
void onZoomChanged(int newZoom);
}
}
And for Camera2:
public class ActiveArrayZoomHandler extends AbstractZoomHandler {
private IZoomHandlerListener zoomHandlerListener;
private Rect activeArraySize;
ActiveArrayZoomHandler(View touchableView) {
super( touchableView );
}
public void setZoomHandlerListener(IZoomHandlerListener zoomHandlerListener) {
this.zoomHandlerListener = zoomHandlerListener;
}
public void setActiveArraySize(Rect activeArraySize) {
this.activeArraySize = activeArraySize;
}
@Override
public void notifyZoomChanged(int zoom) {
int minW = (int) (activeArraySize.width() / maxZoom);
int minH = (int) (activeArraySize.height() / maxZoom);
int difW = activeArraySize.width() - minW;
int difH = activeArraySize.height() - minH;
int cropW = difW / 100 * zoomLevel;
int cropH = difH / 100 * zoomLevel;
cropW -= cropW & 3;
cropH -= cropH & 3;
Rect zoomRect = new Rect( cropW, cropH, activeArraySize.width() - cropW, activeArraySize.height() - cropH );
zoomHandlerListener.onZoomChanged( zoomRect );
}
@Override
public boolean isPrepared() {
return zoomHandlerListener != null && activeArraySize != null;
}
public interface IZoomHandlerListener {
void onZoomChanged(Rect zoom);
}
}
And their respective Builder to make it fluent interface. For camera API:
public class SimpleZoomHandlerBuilder {
private SimpleZoomHandler simpleZoomHandler;
public static SimpleZoomHandlerBuilder forView(View touchableView) {
return new SimpleZoomHandlerBuilder( touchableView );
}
private SimpleZoomHandlerBuilder(View touchableView) {
simpleZoomHandler = new SimpleZoomHandler( touchableView );
}
public SimpleZoomHandlerBuilder setZoomListener(SimpleZoomHandler.IZoomHandlerListener listener) {
simpleZoomHandler.setZoomHandlerListener( listener );
return this;
}
public SimpleZoomHandlerBuilder setMaxZoom(float maxZoom) {
simpleZoomHandler.setMaxZoom( maxZoom );
return this;
}
public SimpleZoomHandler build() {
return simpleZoomHandler;
}
}
And for camera2 API:
public class ActiveArrayZoomHandlerBuilder {
private ActiveArrayZoomHandler activeArrayZoomHandler;
public static ActiveArrayZoomHandlerBuilder forView(View touchableView) {
return new ActiveArrayZoomHandlerBuilder( touchableView );
}
private ActiveArrayZoomHandlerBuilder(View touchableView) {
activeArrayZoomHandler = new ActiveArrayZoomHandler( touchableView );
}
public ActiveArrayZoomHandlerBuilder setZoomListener(ActiveArrayZoomHandler.IZoomHandlerListener listener) {
activeArrayZoomHandler.setZoomHandlerListener( listener );
return this;
}
public ActiveArrayZoomHandlerBuilder setMaxZoom(float maxZoom) {
activeArrayZoomHandler.setMaxZoom( maxZoom );
return this;
}
public ActiveArrayZoomHandlerBuilder setActiveArraySize(Rect activeArraySize) {
activeArrayZoomHandler.setActiveArraySize( activeArraySize );
return this;
}
public ActiveArrayZoomHandler build() {
return activeArrayZoomHandler;
}
}