相機手動對焦(帶動畫效果)
阿新 • • 發佈:2019-02-18
showsf_sv = (SurfaceView)findViewById(R.id.camera_showsf_sv ); // 成像控制元件
showsf_sv.setOnTouchListener(new TouchListener());
private final class TouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
/** 通過與運算保留最後八位 MotionEvent.ACTION_MASK = 255 */
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
//設定聚焦
Point point = new Point((int) event.getX(), (int) event.getY());
onFocus(point, autoFocusCallback);
mFocusImageView.startFocus(point);
break;
}
return true;
}
}
private final Camera.AutoFocusCallback autoFocusCallback=new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
//聚焦之後根據結果修改圖片
isFocusSuccess =success;
if (success) {
mFocusImageView.onFocusSuccess();
}else {
//聚焦失敗顯示的圖片,由於未找到合適的資源,這裡仍顯示同一張圖片
mFocusImageView.onFocusFailed();
}
}
};
/**
* 手動聚焦
* @param point 觸屏座標
*/
protected void onFocus(Point point,Camera.AutoFocusCallback callback){
if(mCamera!=null) {
Camera.Parameters parameters = mCamera.getParameters();
//不支援設定自定義聚焦,則使用自動聚焦,返回
if (parameters.getMaxNumFocusAreas() <= 0) {
mCamera.autoFocus(callback);
return;
}
List<Camera.Area> areas = new ArrayList<Camera.Area>();
int left = point.x - 300;
int top = point.y - 300;
int right = point.x + 300;
int bottom = point.y + 300;
left = left < -1000 ? -1000 : left;
top = top < -1000 ? -1000 : top;
right = right > 1000 ? 1000 : right;
bottom = bottom > 1000 ? 1000 : bottom;
areas.add(new Camera.Area(new Rect(left, top, right, bottom), 100));
parameters.setFocusAreas(areas);
try {
//本人使用的小米手機在設定聚焦區域的時候經常會出異常,看日誌發現是框架層的字串轉int的時候出錯了,
//目測是小米修改了框架層程式碼導致,在此try掉,對實際聚焦效果沒影響
mCamera.setParameters(parameters);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
mCamera.autoFocus(callback);
}
}
聚焦動畫效果
package cn.maketion.app.camera;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import cn.maketion.activity.R;
/**
* @ClassName: FocusImageView
* @Description:聚焦時顯示的ImagView
* @author major
* @date 2016-4-20
*
*/
public class FocusImageView extends ImageView {
public final static String TAG="FocusImageView";
private static final int NO_ID=-1;
private int mFocusImg=NO_ID;
private int mFocusSucceedImg=NO_ID;
private int mFocusFailedImg=NO_ID;
private Animation mAnimation;
private Handler mHandler;
public FocusImageView(Context context) {
super(context);
mAnimation=AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show);
setVisibility(View.GONE);
mHandler=new Handler();
}
public FocusImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mAnimation=AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show);
mHandler=new Handler();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FocusImageView);
mFocusImg = a.getResourceId(R.styleable.FocusImageView_focus_focusing_id, NO_ID);
mFocusSucceedImg=a.getResourceId(R.styleable.FocusImageView_focus_success_id, NO_ID);
mFocusFailedImg=a.getResourceId(R.styleable.FocusImageView_focus_fail_id, NO_ID);
a.recycle();
//聚焦圖片不能為空
if (mFocusImg==NO_ID||mFocusSucceedImg==NO_ID||mFocusFailedImg==NO_ID)
throw new RuntimeException("Animation is null");
}
/**
* 顯示聚焦圖案
* @param x 觸屏的x座標
* @param y 觸屏的y座標
*/
public void startFocus(Point point){
if (mFocusImg==NO_ID||mFocusSucceedImg==NO_ID||mFocusFailedImg==NO_ID)
throw new RuntimeException("focus image is null");
//根據觸控的座標設定聚焦圖案的位置
FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) getLayoutParams();
params.topMargin= point.y-getHeight()/2;
params.leftMargin=point.x-getWidth()/2;
setLayoutParams(params);
//設定控制元件可見,並開始動畫
setVisibility(View.VISIBLE);
setImageResource(mFocusImg);
startAnimation(mAnimation);
//3秒後隱藏View。在此處設定是由於可能聚焦事件可能不觸發。
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},3500);
}
/**
* 聚焦成功回撥
*/
public void onFocusSuccess(){
setImageResource(mFocusSucceedImg);
//移除在startFocus中設定的callback,1秒後隱藏該控制元件
mHandler.removeCallbacks(null, null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},1000);
}
/**
* 聚焦失敗回撥
*/
public void onFocusFailed(){
setImageResource(mFocusFailedImg);
//移除在startFocus中設定的callback,1秒後隱藏該控制元件
mHandler.removeCallbacks(null, null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},1000);
}
/**
* 設定開始聚焦時的圖片
* @param focus
*/
public void setFocusImg(int focus) {
this.mFocusImg = focus;
}
/**
* 設定聚焦成功顯示的圖片
* @param focusSucceed
*/
public void setFocusSucceedImg(int focusSucceed) {
this.mFocusSucceedImg = focusSucceed;
}
}
showsf_sv.setOnTouchListener(new TouchListener());
private final class TouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
/** 通過與運算保留最後八位 MotionEvent.ACTION_MASK = 255 */
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
//設定聚焦
Point point = new Point((int) event.getX(), (int) event.getY());
onFocus(point, autoFocusCallback);
mFocusImageView.startFocus(point);
break;
}
return true;
}
}
private final Camera.AutoFocusCallback autoFocusCallback=new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
//聚焦之後根據結果修改圖片
isFocusSuccess =success;
if (success) {
mFocusImageView.onFocusSuccess();
}else {
//聚焦失敗顯示的圖片,由於未找到合適的資源,這裡仍顯示同一張圖片
mFocusImageView.onFocusFailed();
}
}
};
/**
* 手動聚焦
* @param point 觸屏座標
*/
protected void onFocus(Point point,Camera.AutoFocusCallback callback){
if(mCamera!=null) {
Camera.Parameters parameters = mCamera.getParameters();
//不支援設定自定義聚焦,則使用自動聚焦,返回
if (parameters.getMaxNumFocusAreas() <= 0) {
mCamera.autoFocus(callback);
return;
}
List<Camera.Area> areas = new ArrayList<Camera.Area>();
int left = point.x - 300;
int top = point.y - 300;
int right = point.x + 300;
int bottom = point.y + 300;
left = left < -1000 ? -1000 : left;
top = top < -1000 ? -1000 : top;
right = right > 1000 ? 1000 : right;
bottom = bottom > 1000 ? 1000 : bottom;
areas.add(new Camera.Area(new Rect(left, top, right, bottom), 100));
parameters.setFocusAreas(areas);
try {
//本人使用的小米手機在設定聚焦區域的時候經常會出異常,看日誌發現是框架層的字串轉int的時候出錯了,
//目測是小米修改了框架層程式碼導致,在此try掉,對實際聚焦效果沒影響
mCamera.setParameters(parameters);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
mCamera.autoFocus(callback);
}
}
聚焦動畫效果
package cn.maketion.app.camera;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import cn.maketion.activity.R;
/**
* @ClassName: FocusImageView
* @Description:聚焦時顯示的ImagView
* @author major
* @date 2016-4-20
*
*/
public class FocusImageView extends ImageView {
public final static String TAG="FocusImageView";
private static final int NO_ID=-1;
private int mFocusImg=NO_ID;
private int mFocusSucceedImg=NO_ID;
private int mFocusFailedImg=NO_ID;
private Animation mAnimation;
private Handler mHandler;
public FocusImageView(Context context) {
super(context);
mAnimation=AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show);
setVisibility(View.GONE);
mHandler=new Handler();
}
public FocusImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mAnimation=AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show);
mHandler=new Handler();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FocusImageView);
mFocusImg = a.getResourceId(R.styleable.FocusImageView_focus_focusing_id, NO_ID);
mFocusSucceedImg=a.getResourceId(R.styleable.FocusImageView_focus_success_id, NO_ID);
mFocusFailedImg=a.getResourceId(R.styleable.FocusImageView_focus_fail_id, NO_ID);
a.recycle();
//聚焦圖片不能為空
if (mFocusImg==NO_ID||mFocusSucceedImg==NO_ID||mFocusFailedImg==NO_ID)
throw new RuntimeException("Animation is null");
}
/**
* 顯示聚焦圖案
* @param x 觸屏的x座標
* @param y 觸屏的y座標
*/
public void startFocus(Point point){
if (mFocusImg==NO_ID||mFocusSucceedImg==NO_ID||mFocusFailedImg==NO_ID)
throw new RuntimeException("focus image is null");
//根據觸控的座標設定聚焦圖案的位置
FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) getLayoutParams();
params.topMargin= point.y-getHeight()/2;
params.leftMargin=point.x-getWidth()/2;
setLayoutParams(params);
//設定控制元件可見,並開始動畫
setVisibility(View.VISIBLE);
setImageResource(mFocusImg);
startAnimation(mAnimation);
//3秒後隱藏View。在此處設定是由於可能聚焦事件可能不觸發。
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},3500);
}
/**
* 聚焦成功回撥
*/
public void onFocusSuccess(){
setImageResource(mFocusSucceedImg);
//移除在startFocus中設定的callback,1秒後隱藏該控制元件
mHandler.removeCallbacks(null, null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},1000);
}
/**
* 聚焦失敗回撥
*/
public void onFocusFailed(){
setImageResource(mFocusFailedImg);
//移除在startFocus中設定的callback,1秒後隱藏該控制元件
mHandler.removeCallbacks(null, null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
setVisibility(View.GONE);
}
},1000);
}
/**
* 設定開始聚焦時的圖片
* @param focus
*/
public void setFocusImg(int focus) {
this.mFocusImg = focus;
}
/**
* 設定聚焦成功顯示的圖片
* @param focusSucceed
*/
public void setFocusSucceedImg(int focusSucceed) {
this.mFocusSucceedImg = focusSucceed;
}
}