Finish basic tap to focus

pull/1/head
Dylan McIntyre 8 years ago
parent 29ccf4fa6a
commit fba3ed4ee1
  1. 216
      camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
  2. 2
      camerakit/src/main/res/values/attrs.xml
  3. 71
      demo/src/main/java/com/flurgle/camerakit/demo/FocusMarkerLayout.java
  4. 12
      demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java
  5. 7
      demo/src/main/res/drawable/focus_marker_fill.xml
  6. 9
      demo/src/main/res/drawable/focus_marker_outline.xml
  7. 37
      demo/src/main/res/layout/activity_main.xml
  8. 24
      demo/src/main/res/layout/layout_focus_marker.xml

@ -5,7 +5,6 @@ import android.graphics.YuvImage;
import android.hardware.Camera; import android.hardware.Camera;
import android.media.CamcorderProfile; import android.media.CamcorderProfile;
import android.media.MediaRecorder; import android.media.MediaRecorder;
import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.View; import android.view.View;
@ -19,7 +18,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import static android.content.ContentValues.TAG;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF; import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS; import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_OFF; import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_OFF;
@ -30,11 +28,9 @@ import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STILL;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class Camera1 extends CameraImpl { public class Camera1 extends CameraImpl {
private static final int FOCUS_AREA_SIZE_DEFAULT = 300; private static final int FOCUS_AREA_SIZE_DEFAULT = 300;
private static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 800; private static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 1000;
private View view;
private int mCameraId; private int mCameraId;
private Camera mCamera; private Camera mCamera;
private Camera.Parameters mCameraParameters; private Camera.Parameters mCameraParameters;
@ -46,8 +42,6 @@ public class Camera1 extends CameraImpl {
private Camera.AutoFocusCallback mAutofocusCallback; private Camera.AutoFocusCallback mAutofocusCallback;
private int mDisplayOrientation; private int mDisplayOrientation;
private int mFocusAreaSize = 0;
private int mFocusMeteringAreaWeight = 0;
@Facing @Facing
private int mFacing; private int mFacing;
@ -66,7 +60,6 @@ public class Camera1 extends CameraImpl {
Camera1(CameraListener callback, PreviewImpl preview) { Camera1(CameraListener callback, PreviewImpl preview) {
super(callback, preview); super(callback, preview);
this.view = preview.getView();
preview.setCallback(new PreviewImpl.Callback() { preview.setCallback(new PreviewImpl.Callback() {
@Override @Override
public void onSurfaceChanged() { public void onSurfaceChanged() {
@ -152,6 +145,7 @@ public class Camera1 extends CameraImpl {
switch (focus) { switch (focus) {
case FOCUS_CONTINUOUS: case FOCUS_CONTINUOUS:
if (mCameraParameters != null) { if (mCameraParameters != null) {
detachFocusTapListener();
final List<String> modes = mCameraParameters.getSupportedFocusModes(); final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
@ -162,12 +156,18 @@ public class Camera1 extends CameraImpl {
break; break;
case FOCUS_TAP: case FOCUS_TAP:
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); if (mCameraParameters != null) {
attachFocusTapListener(); attachFocusTapListener();
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
}
break; break;
case FOCUS_OFF: case FOCUS_OFF:
if (mCameraParameters != null) { if (mCameraParameters != null) {
detachFocusTapListener();
final List<String> modes = mCameraParameters.getSupportedFocusModes(); final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) { if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED); mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
@ -295,107 +295,8 @@ public class Camera1 extends CameraImpl {
return mCamera != null; return mCamera != null;
} }
void setFocusAreaSize(int size) {
mFocusAreaSize = size;
}
/**
* @link {@link android.hardware.Camera.Area#weight}
*/
void setFocusMeteringAreaWeight(int weight) {
mFocusMeteringAreaWeight = weight;
}
void setTapToAutofocusListener(Camera.AutoFocusCallback callback) {
if (this.mFocus != FOCUS_TAP) {
throw new IllegalArgumentException("Please set the camera to FOCUS_TAP.");
}
this.mAutofocusCallback = callback;
}
private int getFocusAreaSize() {
if (mFocusAreaSize == 0) {
return FOCUS_AREA_SIZE_DEFAULT;
} else {
return mFocusAreaSize;
}
}
private int getFocusMeteringAreaWeight() {
if (mFocusMeteringAreaWeight == 0) {
return FOCUS_METERING_AREA_WEIGHT_DEFAULT;
} else {
return mFocusMeteringAreaWeight;
}
}
// Internal: // Internal:
private void attachFocusTapListener() {
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
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<>();
meteringAreas.add(new Camera.Area(rect, FOCUS_METERING_AREA_WEIGHT_DEFAULT));
parameters.setFocusAreas(meteringAreas);
mCamera.setParameters(parameters);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (mAutofocusCallback != null) {
mAutofocusCallback.onAutoFocus(success, camera);
}
}
});
} else {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (mAutofocusCallback != null) {
mAutofocusCallback.onAutoFocus(success, camera);
}
}
});
}
}
}
return true;
}
});
}
private Rect calculateFocusArea(float x, float y) {
int left = clamp(Float.valueOf((x / view.getWidth()) * 2000 - 1000).intValue(), getFocusAreaSize());
int top = clamp(Float.valueOf((y / view.getHeight()) * 2000 - 1000).intValue(), getFocusAreaSize());
return new Rect(left, top, left + getFocusAreaSize(), top + getFocusAreaSize());
}
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 void openCamera() { private void openCamera() {
if (mCamera != null) { if (mCamera != null) {
releaseCamera(); releaseCamera();
@ -520,4 +421,101 @@ public class Camera1 extends CameraImpl {
} }
} }
void setTapToAutofocusListener(Camera.AutoFocusCallback callback) {
if (this.mFocus != FOCUS_TAP) {
throw new IllegalArgumentException("Please set the camera to FOCUS_TAP.");
}
this.mAutofocusCallback = callback;
}
private int getFocusAreaSize() {
return FOCUS_AREA_SIZE_DEFAULT;
}
private int getFocusMeteringAreaWeight() {
return FOCUS_METERING_AREA_WEIGHT_DEFAULT;
}
private void detachFocusTapListener() {
mPreview.getView().setOnTouchListener(null);
}
private void attachFocusTapListener() {
mPreview.getView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
if (parameters.getMaxNumMeteringAreas() > 0) {
Rect rect = calculateFocusArea(event.getX(), event.getY());
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
List<Camera.Area> meteringAreas = new ArrayList<>();
meteringAreas.add(new Camera.Area(rect, getFocusMeteringAreaWeight()));
parameters.setFocusAreas(meteringAreas);
parameters.setMeteringAreas(meteringAreas);
mCamera.setParameters(parameters);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
camera.cancelAutoFocus();
Camera.Parameters params = camera.getParameters();
if (params.getFocusMode() != Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
params.setFocusAreas(null);
params.setMeteringAreas(null);
camera.setParameters(params);
}
if (mAutofocusCallback != null) {
mAutofocusCallback.onAutoFocus(success, camera);
}
}
});
} else {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (mAutofocusCallback != null) {
mAutofocusCallback.onAutoFocus(success, camera);
}
}
});
}
}
}
return true;
}
});
}
private Rect calculateFocusArea(float x, float y) {
int centerX = clamp(Float.valueOf((x / mPreview.getView().getWidth()) * 2000 - 1000).intValue(), getFocusAreaSize());
int centerY = clamp(Float.valueOf((y / mPreview.getView().getHeight()) * 2000 - 1000).intValue(), getFocusAreaSize());
return new Rect(
centerX - getFocusAreaSize() / 2,
centerY - getFocusAreaSize() / 2,
centerX + getFocusAreaSize() / 2,
centerY + getFocusAreaSize() / 2
);
}
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;
}
} }

@ -19,7 +19,7 @@
<enum name="continuous" value="1" /> <enum name="continuous" value="1" />
<!-- TODO: Set to unique value when feature added --> <!-- TODO: Set to unique value when feature added -->
<enum name="tap" value="1" /> <enum name="tap" value="2" />
</attr> </attr>
<attr name="ckZoom" format="enum"> <attr name="ckZoom" format="enum">

@ -0,0 +1,71 @@
package com.flurgle.camerakit.demo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class FocusMarkerLayout extends FrameLayout {
private FrameLayout mFocusMarkerContainer;
private ImageView mFill;
public FocusMarkerLayout(@NonNull Context context) {
super(context, null);
}
public FocusMarkerLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(getContext()).inflate(R.layout.layout_focus_marker, this);
mFocusMarkerContainer = (FrameLayout) findViewById(R.id.focusMarkerContainer);
mFill = (ImageView) findViewById(R.id.fill);
mFocusMarkerContainer.setAlpha(0);
}
public void focus(float mx, float my) {
int x = (int) (mx - mFocusMarkerContainer.getWidth() / 2);
int y = (int) (my - mFocusMarkerContainer.getWidth() / 2);
mFocusMarkerContainer.setTranslationX(x);
mFocusMarkerContainer.setTranslationY(y);
mFocusMarkerContainer.animate().setListener(null).cancel();
mFill.animate().setListener(null).cancel();
mFill.setScaleX(0);
mFill.setScaleY(0);
mFill.setAlpha(1f);
mFocusMarkerContainer.setScaleX(1.36f);
mFocusMarkerContainer.setScaleY(1.36f);
mFocusMarkerContainer.setAlpha(1f);
mFocusMarkerContainer.animate().scaleX(1).scaleY(1).setStartDelay(0).setDuration(330)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mFocusMarkerContainer.animate().alpha(0).setStartDelay(750).setDuration(800).setListener(null).start();
}
}).start();
mFill.animate().scaleX(1).scaleY(1).setDuration(330)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mFill.animate().alpha(0).setDuration(800).setListener(null).start();
}
}).start();
}
}

@ -5,6 +5,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
@ -23,6 +24,7 @@ import java.io.File;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.OnTouch;
public class MainActivity extends AppCompatActivity implements View.OnLayoutChangeListener { public class MainActivity extends AppCompatActivity implements View.OnLayoutChangeListener {
@ -32,6 +34,9 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan
@BindView(R.id.camera) @BindView(R.id.camera)
CameraView camera; CameraView camera;
@BindView(R.id.focusMarker)
FocusMarkerLayout focusMarker;
// Capture Mode: // Capture Mode:
@BindView(R.id.captureModeRadioGroup) @BindView(R.id.captureModeRadioGroup)
@ -308,4 +313,11 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan
camera.removeOnLayoutChangeListener(this); camera.removeOnLayoutChangeListener(this);
} }
@OnTouch(R.id.focusMarker)
boolean onTouchCamera(View view, MotionEvent motionEvent) {
focusMarker.focus(motionEvent.getX(), motionEvent.getY());
return false;
}
} }

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#77FFFFFF" />
</shape>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="1.5dp"
android:color="@android:color/white" />
</shape>

@ -13,18 +13,33 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<com.flurgle.camerakit.CameraView xmlns:app="http://schemas.android.com/apk/res-auto" <RelativeLayout
android:id="@+id/camera"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="500dp" android:layout_height="wrap_content">
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true" <com.flurgle.camerakit.CameraView xmlns:app="http://schemas.android.com/apk/res-auto"
app:ckCropOutput="false" android:id="@+id/camera"
app:ckFacing="back" android:layout_width="match_parent"
app:ckFlash="off" android:layout_height="400dp"
app:ckFocus="continuous" android:layout_gravity="center_horizontal"
app:ckJpegQuality="100" android:adjustViewBounds="true"
app:ckMethod="standard" /> app:ckCropOutput="false"
app:ckFacing="back"
app:ckFlash="off"
app:ckFocus="tap"
app:ckJpegQuality="100"
app:ckMethod="standard" />
<com.flurgle.camerakit.demo.FocusMarkerLayout
android:id="@+id/focusMarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/camera"
android:layout_alignLeft="@+id/camera"
android:layout_alignRight="@+id/camera"
android:layout_alignTop="@+id/camera" />
</RelativeLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/focusMarkerContainer"
android:layout_width="55dp"
android:layout_height="55dp">
<ImageView
android:id="@+id/fill"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/focus_marker_fill" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/focus_marker_outline" />
</FrameLayout>
</FrameLayout>
Loading…
Cancel
Save