Skip to content

Instantly share code, notes, and snippets.

@FisherKK
Created October 29, 2015 13:18
Show Gist options
  • Save FisherKK/ca209e4cb740b65b4ee6 to your computer and use it in GitHub Desktop.
Save FisherKK/ca209e4cb740b65b4ee6 to your computer and use it in GitHub Desktop.
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
Camera.Size mPreviewSize;
List<Camera.Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mCamera.setDisplayOrientation(90);
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
viewHeight = AppTools.getScreenHeight(CameraActivity.this);
viewWidth = width;
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth=mPreviewSize.height;
previewHeight=mPreviewSize.width;
}
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
if (parameters.getSupportedPictureSizes() != null) {
parameters = initialCameraPictureSize(parameters, mPreviewSize.width, mPreviewSize.height);
}
parameters = adjustFocusToDevice(parameters);
makeCameraViewSquare();
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
public Camera.Parameters initialCameraPictureSize(Camera.Parameters parameters, int w, int h) {
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
final double ASPECT_TOLERANCE = 0.1;
double targetRatio= AppTools.getScreenRatio(CameraActivity.this);
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
if (optimalSize.height > 1600 || optimalSize.width > 1600) continue;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
parameters.setPictureSize(optimalSize.width,optimalSize.height);
return parameters;
}
private void makeCameraViewSquare() {
topView.setLayoutParams(new RelativeLayout.LayoutParams(
viewWidth,
(viewHeight - viewWidth)/2
));
RelativeLayout.LayoutParams bottomViewParams = new RelativeLayout.LayoutParams(
viewWidth,
(viewHeight - viewWidth)/2
);
bottomViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
bottomView.setLayoutParams(bottomViewParams);
llCameraButtonbar.setLayoutParams(bottomViewParams);
}
}
private Camera.Parameters adjustFocusToDevice(Camera.Parameters parameters) {
List<String> focusModesList = parameters.getSupportedFocusModes();
for (int i=0; i<=focusModesList.size()-1; i++) {
if (currentCamera != FRONT_CAMERA) {
if (focusModesList.get(i).contains("continuous-picture")) {
currentFocusMode = CONTINUOUS_PICTURE_MODE;
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (focusModesList.get(i).contains("auto")) {
currentFocusMode = AUTO_FOCUS_MODE;
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
}
}
return parameters;
}
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
if (currentCamera == FRONT_CAMERA) {
return true;
}
if (currentFocusMode != null && currentFocusMode == AUTO_FOCUS_MODE && !isTakePictureClicked) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
}
});
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment