package com.laifeng.sopcastsdk.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.laifeng.sopcastsdk.R;
import com.laifeng.sopcastsdk.camera.CameraData;
import com.laifeng.sopcastsdk.camera.CameraHolder;
import com.laifeng.sopcastsdk.camera.CameraZoomListener;
import com.laifeng.sopcastsdk.camera.focus.FocusManager;
import com.laifeng.sopcastsdk.camera.focus.FocusPieView;
import com.laifeng.sopcastsdk.utils.WeakHandler;
import com.laifeng.sopcastsdk.video.MyRenderer;
/**
* @Title: CameraView
* @Package com.laifeng.sopcastsdk.ui
* @Description:
* @Author Jim
* @Date 16/9/18
* @Time 下午5:31
* @Version
*/
public class CameraView extends FrameLayout {
private Context mContext;
protected RenderSurfaceView mRenderSurfaceView;
protected MyRenderer mRenderer;
private FocusPieView mFocusHudRing;
private FocusManager mFocusManager;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mZoomGestureDetector;
private WeakHandler mHandler;
private boolean mIsFocusing;
private CameraZoomListener mZoomListener;
private boolean isFocusTouchMode = false;
private boolean isMediaOverlay;
private boolean isRenderSurfaceViewShowing = true;
private float mAspectRatio = 9.0f/16;
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initView();
initAspectRatio(attrs);
}
public CameraView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initView();
initAspectRatio(attrs);
}
public CameraView(Context context) {
super(context);
mContext = context;
initView();
}
private void initView() {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mInflater.inflate(R.layout.layout_camera_view, this, true);
mHandler = new WeakHandler();
mRenderSurfaceView = (RenderSurfaceView) findViewById(R.id.render_surface_view);
mRenderSurfaceView.setZOrderMediaOverlay(isMediaOverlay);
mRenderer = mRenderSurfaceView.getRenderer();
mFocusHudRing = (FocusPieView) findViewById(R.id.focus_view);
mFocusManager = new FocusManager();
mFocusManager.setListener(new MainFocusListener());
mGestureDetector = new GestureDetector(mContext, new GestureListener());
mZoomGestureDetector = new ScaleGestureDetector(mContext, new ZoomGestureListener());
}
private void initAspectRatio(AttributeSet attrs) {
TypedArray a = mContext.obtainStyledAttributes(attrs,
R.styleable.CameraLivingView);
mAspectRatio = a.getFloat(R.styleable.CameraLivingView_aspect_ratio, 9.0f / 16);
}
public void setOnZoomProgressListener(CameraZoomListener listener) {
mZoomListener = listener;
}
@Override
public void setVisibility(int visibility) {
int currentVisibility = getVisibility();
if(visibility == currentVisibility) {
return;
}
switch (visibility) {
case VISIBLE:
addRenderSurfaceView();
break;
case GONE:
removeRenderSurfaceView();
break;
case INVISIBLE:
removeRenderSurfaceView();
break;
}
super.setVisibility(visibility);
}
private void addRenderSurfaceView() {
if(!isRenderSurfaceViewShowing) {
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
addView(mRenderSurfaceView, 0, layoutParams);
isRenderSurfaceViewShowing = true;
}
}
private void removeRenderSurfaceView() {
if(isRenderSurfaceViewShowing) {
removeView(mRenderSurfaceView);
isRenderSurfaceViewShowing = false;
}
}
/**
* Focus listener to animate the focus HUD ring from FocusManager events
*/
private class MainFocusListener implements FocusManager.FocusListener {
@Override
public void onFocusStart() {
mIsFocusing = true;
mFocusHudRing.setVisibility(VISIBLE);
mFocusHudRing.animateWorking(1500);
requestLayout();
}
@Override
public void onFocusReturns(final boolean success) {
mIsFocusing = false;
mFocusHudRing.setFocusImage(success);
mFocusHudRing.setVisibility(INVISIBLE);
requestLayout();
}
}
public class GestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mFocusManager != null) {
mFocusHudRing.setPosition(e.getX(), e.getY());
mFocusManager.refocus();
}
return super.onSingleTapConfirmed(e);
}
}
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
this.isMediaOverlay = isMediaOverlay;
if(mRenderSurfaceView != null) {
mRenderSurfaceView.setZOrderMediaOverlay(isMediaOverlay);
}
}
/**
* Handles the pinch-to-zoom gesture
*/
private class ZoomGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
if (!mIsFocusing) {
float progress = 0;
if (detector.getScaleFactor() > 1.0f) {
progress = CameraHolder.instance().cameraZoom(true);
} else if (detector.getScaleFactor() < 1.0f) {
progress = CameraHolder.instance().cameraZoom(false);
} else {
return false;
}
if(mZoomListener != null) {
mZoomListener.onZoomProgress(progress);
}
}
return true;
}
}
protected void changeFocusModeUI() {
CameraData cameraData = CameraHolder.instance().getCameraData();
if(cameraData != null && cameraData.supportTouchFocus && cameraData.touchFocusMode) {
isFocusTouchMode = true;
if (mFocusManager != null) {
mHandler.postDelayed(new Runnable() {
public void run() {
mFocusHudRing.resetPosition();
mFocusManager.refocus();
}
}, 1000);
}
} else {
isFocusTouchMode = false;
mFocusHudRing.setVisibility(INVISIBLE);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(isFocusTouchMode) {
return mGestureDetector.onTouchEvent(event) || mZoomGestureDetector.onTouchEvent(event);
} else {
return mZoomGestureDetector.onTouchEvent(event);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
if(widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.AT_MOST) {
heightSpecSize = (int)(widthSpecSize / mAspectRatio);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSpecSize,
MeasureSpec.EXACTLY);
} else if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.EXACTLY) {
widthSpecSize = (int)(heightSpecSize * mAspectRatio);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSpecSize,
MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}