总结一下自定义相机实现几个功能:根据手势拉近拉远摄像头,实现手动对焦,打开或关闭摄像头。
实现思路:界面的控制与底层相机的操作分开执行,先实现界面的控制,在调用相应的函数实现功能。
界面上实现 手势的放大或缩小手指的聚焦。
增加一个小知识点:
通过Handler实现view的自动隐藏
在showView中增加mHandler.sendEmptyMessageDelayed(msg, 2000) ;后在接收handler的时候hideView();如果操作view时operaView(),移除mHandler.remove(msg);操作结束在执行函数mHandler.sendEmptyMessageDelayed(msg, 2000) ;
核心代码:
public class GestureRecognizer {
/**
* 标签
*/
public static final String TAG = GestureRecognizer.class.getSimpleName();
public interface Listener {
boolean onSingleTapUp(float x, float y);
boolean onDoubleTap(float x, float y);
boolean onScroll(float dx, float dy, float totalX, float totalY);
boolean onFling(float velocityX, float velocityY);
boolean onScaleBegin(float focusX, float focusY);
boolean onScale(float focusX, float focusY, float scale);
void onScaleEnd();
void onDown(float x, float y);
void onUp();
}
private final GestureDetector mGestureDetector;
private final ScaleGestureDetector mScaleDetector;
private final DownUpDetector mDownUpDetector;
private final Listener mListener;
public GestureRecognizer(Context context, Listener listener) {
Handler handler = new Handler(context.getMainLooper());
mListener = listener;
mGestureDetector = new GestureDetector(context, new MyGestureListener(), handler, true /* ignoreMultitouch */);
mScaleDetector = new ScaleGestureDetector(context, new MyScaleListener());
mDownUpDetector = new DownUpDetector(new MyDownUpListener());
}
public void onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
mDownUpDetector.onTouchEvent(event);
}
public boolean isDown() {
return mDownUpDetector.isDown();
}
public void cancelScale() {
long now = SystemClock.uptimeMillis();
MotionEvent cancelEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
mScaleDetector.onTouchEvent(cancelEvent);
cancelEvent.recycle();
}
private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return mListener.onSingleTapUp(e.getX(), e.getY());
}
@Override
public boolean onDoubleTap(MotionEvent e) {
return mListener.onDoubleTap(e.getX(), e.getY());
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) {
return mListener.onScroll(dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY());
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return mListener.onFling(velocityX, velocityY);
}
}
private class MyScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return mListener.onScaleBegin(detector.getFocusX(), detector.getFocusY());
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
return mListener.onScale(detector.getFocusX(), detector.getFocusY(), detector.getScaleFactor());
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mListener.onScaleEnd();
}
}
private class MyDownUpListener implements DownUpDetector.DownUpListener {
@Override
public void onDown(MotionEvent e) {
mListener.onDown(e.getX(), e.getY());
}
@Override
public void onUp(MotionEvent e) {
mListener.onUp();
}
}
}
实现代码:
public class ViewOfVideoCallListener implements
com.xinwei.pnas.view.GestureRecognizer.Listener,
PnasMediaAgent.IOnAutoFocusCallBack, PnasMediaAgent.IOnChangeCamera{
private WeakReference wefHandler;
private Handler mHandler;
private PnasMediaAgent mPnasMediaAgent;
private int flag;
/**
* 视频组呼
*/
public static final int GROUPVIDEOVALLFLAG=1;
/**
* 视频单呼
*/
public static final int SINGLEVIDEOVALLFLAG=2;
public ViewOfVideoCallListener(Context nContext, Handler nHandler) {
super();
this.mContext = nContext;
this.wefHandler = new WeakReference(nHandler);
mHandler = new MainHandler(mContext.getMainLooper());
mPnasMediaAgent = this.getPnasMediaAgent();
if(mPnasMediaAgent!=null){
mPnasMediaAgent.setIOnChangeCamera(this) ;
}
}
public ViewOfVideoCallListener(Context nContext, Handler nHandler,int flag) {
super();
this.mContext = nContext;
this.wefHandler = new WeakReference(nHandler);
mHandler = new MainHandler(mContext.getMainLooper());
mPnasMediaAgent = this.getPnasMediaAgent();
if(mPnasMediaAgent!=null){
mPnasMediaAgent.setIOnChangeCamera(this) ;
}
this.flag=flag;
}
private static final String TAG = ViewOfVideoCallListener.class
.getSimpleName();
/**
* 重新聚焦
*/
public static final int WHAT_RESET_TOUCH_FOCUS = 1;
public static final int WHAT_HIDE_SEEKBAR = WHAT_RESET_TOUCH_FOCUS + 1;
public static final int WHAT_CAMARA_ZOOM = WHAT_HIDE_SEEKBAR + 1;
private static final int WHAT_CAMARA_FOCUS = WHAT_CAMARA_ZOOM + 1;
private static final int WHAT_RESET_CAMERA_FOCUS = WHAT_CAMARA_FOCUS + 1;
private static final int WHAT_CAMARA_FOCUS_CALLBACK = WHAT_RESET_CAMERA_FOCUS + 1;
private static final int SCALETYPE = 0;
private static final int PROGRESSTYPE = 1;
/**
* 呼叫的状态
*/
private int mcallState;
/**
* 呼叫的类型
*/
private int mcallType;
/**
* 呼叫时的底部操作按钮
*/
private View mOperaVideoCallView;
/**
* 呼叫时的视频的对焦显示框
*/
private View mFocusView;
/**
* 呼叫时的视频的surfaceView的父布局
*/
private View mFrameLayout;
private Context mContext;
/**
* 手势放大或缩小的操作 true 存在 false 不存在
*/
private boolean mIsScallBegin;
/**
* 显示镜头远近的seekbar
*/
private SeekBar mSeekbar;
/**
* 是否开启自动隐藏底部 的操作按钮
*/
private boolean isAutoHide;
private long DELAYMILLIS = 3000;
private int mPreviewHeight;
private int mPreviewWidth;
private FocusIndicatorRotateLayout mFocusAreaIndicator;
private ArrayList mFocusArea;
/**
* 记录最后的放大或缩小的scale得值
*/
private float lastScale;
/**
* 执行放大或缩小的函数 是否执行
*/
public boolean isZoomSucess;
/**
* 摄像头支持的最大聚焦区域
*/
final protected Rect focusMaxRect = new Rect(-1000, -1000, 1000, 1000);
private int maxZoom;
private int mPttcallState;
@Override
public boolean onSingleTapUp(float x, float y) {
Log.d(TAG, "onSingleTapUp" + "mcallState" + mcallState);
if (isAutoHide && mOperaVideoCallView != null
&&((this.flag==SINGLEVIDEOVALLFLAG&& mcallState == CallAgent.CALL_STATE_INCALL))||this.flag==GROUPVIDEOVALLFLAG) {// 通话中才处理
boolean isVisible = (mOperaVideoCallView.getVisibility() == View.VISIBLE);
Log.d(TAG, "isVisible" + isVisible);
if (!isVisible) {
mOperaVideoCallView.setVisibility(View.VISIBLE);
wefHandler.get().sendEmptyMessageDelayed(
SingleVideoCallActivity.WHAT_MSG_HIDE, DELAYMILLIS);
} else {
wefHandler.get().removeMessages(
SingleVideoCallActivity.WHAT_MSG_HIDE);
mOperaVideoCallView.setVisibility(View.INVISIBLE);
}
}
hideView(mSeekbar);
if (mIsScallBegin) {
return true;
}
// 回传本地的视频时才显示对焦的视图
boolean isFocusView=(this.flag==SINGLEVIDEOVALLFLAG&& (mcallType == ExtendedCallAgent.CALL_TYPE_SINGLE_VIDEO_BACK_UP
|| mcallType == ExtendedCallAgent.CALL_TYPE_SINGLE_VIDEO_PUSH))||(this.flag==GROUPVIDEOVALLFLAG&&this.mPttcallState==ExtendedCallAgent.PTT_STATE_SPEAKER);
if(isFocusView) {
showFocusView(x, y);
}
return false;
}
/**
* 显示对焦的视图
*
* @param x
* @param y
*/
private void showFocusView(float x, float y) {
resetTouchFocus();
showView(mFocusView,-1);
setPreviewSize(mFrameLayout.getMeasuredWidth(),
mFrameLayout.getMeasuredHeight());
Log.d(TAG, "mFocusView.getVisibility()" + mFocusView.getVisibility());
focusOnTouch((int) x, (int) y);
autofocus(mFocusArea);
}
private void autofocus(ArrayList focusArea) {
Message msg = mHandler.obtainMessage();
msg.what = WHAT_CAMARA_FOCUS;
msg.obj = focusArea;
mHandler.removeMessages(WHAT_CAMARA_FOCUS);
mHandler.sendMessage(msg);
}
/**
* 显示对焦框
*
* @param x
* @param y
*/
private void focusOnTouch(int x, int y) {
// Initialize variables.
int focusWidth = this.mFocusAreaIndicator.getWidth();
int focusHeight = this.mFocusAreaIndicator.getHeight();
int previewWidth = mPreviewWidth;
int previewHeight = mPreviewHeight;
if (mFocusArea == null) {
mFocusArea = new ArrayList();
mFocusArea.add(new Area(new Rect(), 1));
}
Log.d(TAG, "focusWidth" + focusWidth + ",focusHeight" + focusHeight
+ ",previewWidth" + previewWidth + ",previewHeight"
+ previewHeight);
calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth,
previewHeight, mFocusArea.get(0).rect);
// Use margin to set the focus indicator to the touched area.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) this.mFocusAreaIndicator
.getLayoutParams();
int left = FocusUtil.clamp(x - focusWidth / 2, 0, previewWidth
- focusWidth);
int top = FocusUtil.clamp(y - focusHeight / 2, 0, previewHeight
- focusHeight);
Log.d(TAG, "left" + left + "top" + top);
p.setMargins(left, top, 0, 0);
int[] rules = p.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = 0;
this.mFocusAreaIndicator.requestLayout();
mFocusAreaIndicator.showStart();
mHandler.sendEmptyMessageDelayed(WHAT_RESET_CAMERA_FOCUS, 1500);
}
/**
* 计算对焦的区域
*
* @param focusWidth
* @param focusHeight
* @param areaMultiple
* @param x
* @param y
* @param previewWidth
* @param previewHeight
* @param rect
*/
private void calculateTapArea(int focusWidth, int focusHeight,
float areaMultiple, int x, int y, int previewWidth,
int previewHeight, Rect rect) {
int areaWidth = (int) (focusWidth * areaMultiple);
int areaHeight = (int) (focusHeight * areaMultiple);
int left = FocusUtil.clamp(x - areaWidth / 2, 0, previewWidth
- areaWidth);
int top = FocusUtil.clamp(y - areaHeight / 2, 0, previewHeight
- areaHeight);
RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
FocusUtil.rectFToRect(rectF, rect);
}
@Override
public boolean onDoubleTap(float x, float y) {
Log.d(TAG, "onDoubleTap");
return false;
}
@Override
public boolean onScroll(float dx, float dy, float totalX, float totalY) {
Log.d(TAG, "onScroll");
hideView(mFocusView);
// 回传本地的视频时才会放大和缩小手势的监控,其他此类手势无效
if (mcallType == CallAgent.CALL_TYPE_SINGLE_VIDEO) {
// 显示seekbar
showView(mSeekbar,WHAT_HIDE_SEEKBAR);
return true;
}
return true;
}
@Override
public boolean onFling(float velocityX, float velocityY) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onScaleBegin(float focusX, float focusY) {
Log.d(TAG, "onScaleBegin");
// 隐藏聚焦的按钮
hideView(mFocusView);
// 回传本地的视频时才会放大和缩小手势的监控,其他此类手势无效
boolean isZoomView=(this.flag==SINGLEVIDEOVALLFLAG&& (mcallType == ExtendedCallAgent.CALL_TYPE_SINGLE_VIDEO_BACK_UP
|| mcallType == ExtendedCallAgent.CALL_TYPE_SINGLE_VIDEO_PUSH))||(this.flag==GROUPVIDEOVALLFLAG&&this.mPttcallState==ExtendedCallAgent.PTT_STATE_SPEAKER);
if (isZoomView) {
mIsScallBegin = true;
maxZoom = mPnasMediaAgent.getCameraMaxZoom();
// 显示seekbar
mHandler.removeMessages(WHAT_HIDE_SEEKBAR);
showView(mSeekbar,WHAT_HIDE_SEEKBAR);
if (maxZoom > 0) {
mSeekbar.setMax(maxZoom);
}
isZoomSucess = false;
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
return true;
}
return false;
}
/**
* 隐藏view
*
* @param view
*/
private void hideView(View view) {
if (view == null) {
Log.e(TAG, " hideView NullPointerException");
return;
}
if (view.getVisibility() != View.GONE) {
view.setVisibility(View.GONE);
}
}
/**
* 隐藏view
*
* @param view
*/
private void showView(View view,int msg) {
if (view == null) {
Log.e(TAG, " showView NullPointerException");
return;
}
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
if(msg!=-1){
mHandler.sendEmptyMessageDelayed(msg, 2000) ;
}
}
@Override
public boolean onScale(float focusX, float focusY, float scale) {
Log.d(TAG, "onScale scale" + scale);
lastScale = scale;
mHandler.removeMessages(WHAT_HIDE_SEEKBAR);
return false;
}
@Override
public void onScaleEnd() {
Log.d(TAG, "onScaleEnd");
mIsScallBegin = false;
// 执行相机放大或缩小相机的操作
handlerSentCameraZoom(isZoomSucess, (int) lastScale, SCALETYPE);
mHandler.sendEmptyMessageDelayed(WHAT_HIDE_SEEKBAR, 2000);
}
/**
*
* @param isZoomSucess
* @param value
* @param operaType
*/
private void handlerSentCameraZoom(boolean isZoomSucess, int value,
int operaType) {
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
if (!isZoomSucess) {
Message msg = mHandler.obtainMessage();
msg.what = WHAT_CAMARA_ZOOM;
msg.arg1 = value;
msg.arg2 = operaType;
mHandler.sendMessageDelayed(msg, 50);
}
}
@Override
public void onDown(float x, float y) {
Log.d(TAG, "onDown");
}
@Override
public void onUp() {
Log.d(TAG, "onup");
}
public int getMcallState() {
return mcallState;
}
public void setMcallState(int mcallState) {
this.mcallState = mcallState;
}
/**
* 手势滑动显示的view
*/
public void setScalltoView(SeekBar seekbar) {
this.mSeekbar = seekbar;
initSeekbarTouchListener();
}
private void initSeekbarTouchListener() {
if (mSeekbar != null) {
mSeekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar seekBar) {
try {
int progress = seekBar.getProgress();
handlerSentCameraZoom(isZoomSucess, progress,
PROGRESSTYPE);
} catch (Exception e) {
Log.e(TAG, "setZoom", e);
}
mHandler.sendEmptyMessageDelayed(WHAT_HIDE_SEEKBAR, 2000);
}
public void onStartTrackingTouch(SeekBar seekBar) {
isZoomSucess = false;
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
mHandler.removeMessages(WHAT_HIDE_SEEKBAR);
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mHandler.removeMessages(WHAT_HIDE_SEEKBAR);
}
});
}
}
public void setMcallType(int mcallType) {
this.mcallType = mcallType;
}
public View getmFrameLayout() {
return mFrameLayout;
}
public void setmFrameLayout(ViewGroup mFrameLayout) {
this.mFrameLayout = mFrameLayout;
createFocusAreaIndicator(mFrameLayout);
}
/**
* 对焦显示的视图
*/
public void setFocusView(View focusView) {
this.mFocusView = focusView;
}
public void setAutoHide(boolean isAutoHide) {
checkNotNUll();
this.isAutoHide = isAutoHide;
}
private void checkNotNUll() {
if (this == null) {
return;
}
}
/**
* 底部的操作view
*/
public void setOperaVideoCallView(View operaView) {
this.mOperaVideoCallView = operaView;
}
/**
* create focusAreaIndicator
*
* return
*
* @see #mFocusAreaIndicator
*/
public void createFocusAreaIndicator(ViewGroup previewLayout) {
View focusAreaIndicator = LayoutInflater.from(mContext).inflate(
R.layout.focus_indicator, previewLayout);
this.mFocusAreaIndicator = (FocusIndicatorRotateLayout) focusAreaIndicator
.findViewById(R.id.focus_indicator_rotate_layout);
mFocusView = this.mFocusAreaIndicator
.findViewById(R.id.focus_indicator);
}
private void setPreviewSize(int previewWidth, int previewHeight) {
Log.d(TAG, "setPreviewSize" + previewWidth + "=previewWidth"
+ ",previewHeight" + previewHeight + ",mPreviewWidth"
+ mPreviewWidth + "," + mPreviewHeight);
if (mPreviewWidth != previewWidth || mPreviewHeight != previewHeight) {
mPreviewWidth = previewWidth;
mPreviewHeight = previewHeight;
// Set the length of focus indicator according to preview frame
// size.
int len = Math.min(mPreviewWidth, mPreviewHeight) / 4;
ViewGroup.LayoutParams layout = mFocusView.getLayoutParams();
layout.width = len;
layout.height = len;
Log.d(TAG, "layout.width" + layout.width);
}
}
/**
* 重置对焦框
*/
public void resetTouchFocus() {
mHandler.removeMessages(WHAT_RESET_CAMERA_FOCUS);
if(mFocusAreaIndicator!=null){
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mFocusAreaIndicator
.getLayoutParams();
int[] rules = p.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE;
p.setMargins(0, 0, 0, 0);
mFocusAreaIndicator.clear();
}
}
/**
* 清空view
*/
public void clearView() {
mHandler.removeMessages(WHAT_CAMARA_FOCUS);
mHandler.removeMessages(WHAT_CAMARA_FOCUS_CALLBACK);
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
mHandler.removeMessages(WHAT_HIDE_SEEKBAR);
mHandler.removeMessages(WHAT_RESET_CAMERA_FOCUS);
mHandler.removeMessages(WHAT_RESET_TOUCH_FOCUS);
resetTouchFocus();
mFocusArea = null;
mFocusView = null;
mFrameLayout = null;
mOperaVideoCallView = null;
mSeekbar = null;
if(mPnasMediaAgent!=null){
mPnasMediaAgent.setIOnChangeCamera(null) ;
}
}
/**
* 由于关于camera的操作只能一个一个进行,因此最终通过handker调用
*
* @author xueqian
*
*/
private class MainHandler extends Handler {
public MainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_RESET_TOUCH_FOCUS:
cancelAutoFocus();
break;
case WHAT_HIDE_SEEKBAR:
ViewOfVideoCallListener.this.hideView(mSeekbar);
break;
case WHAT_CAMARA_ZOOM:
operarCameraZoom(msg);
break;
case WHAT_CAMARA_FOCUS:
operarCameraFocus(msg);
break;
case WHAT_RESET_CAMERA_FOCUS:
resetTouchFocus();
break;
case WHAT_CAMARA_FOCUS_CALLBACK:
callBackFocus(msg);
break;
}
}
private void operarCameraZoom(Message msg) {
if (msg.arg2 == SCALETYPE) {
if (!isZoomSucess) {
try {
int zoom = 1;
int scale = msg.arg1;
Log.d(TAG, "MESSAGE_WHAT_CONTROL_ZOOM" + ",zoom" + zoom
+ ",scale" + scale);
if (scale >= 1 && scale <= maxZoom && zoom < maxZoom) {
if (mPnasMediaAgent != null) {
zoom++;
Log.d(TAG, "zoom" + zoom);
mPnasMediaAgent.setCameraZoom(zoom);
if(mSeekbar!=null){
mSeekbar.setProgress(zoom);
}
isZoomSucess = true;
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
}
} else if (scale < 1 && zoom >= 1) {
zoom--;
Log.d(TAG, "zoom" + zoom);
mPnasMediaAgent.setCameraZoom(zoom);
if(mSeekbar!=null){
mSeekbar.setProgress(zoom);
}
isZoomSucess = true;
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
}
} catch (Exception e) {
Log.e(TAG, "control zoom failed", e);
isZoomSucess = false;
}
} else {
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
}
} else if (msg.arg2 == PROGRESSTYPE) {
try {
int scale = msg.arg1;
mPnasMediaAgent.setCameraZoom(scale);
isZoomSucess = true;
mHandler.removeMessages(WHAT_CAMARA_ZOOM);
} catch (Exception e) {
isZoomSucess = true;
}
}
}
}
public void cancelAutoFocus() {
}
public void callBackFocus(Message msg) {
if (mFocusAreaIndicator != null) {
boolean sucessful = (Boolean) msg.obj;
if (sucessful) {
mFocusAreaIndicator.showSuccess(false);
} else {
mFocusAreaIndicator.showFail(false);
}
mHandler.sendEmptyMessageDelayed(WHAT_RESET_CAMERA_FOCUS, 2000);
}
}
public void operarCameraFocus(Message msg) {
try {
ArrayList area = (ArrayList) msg.obj;
mPnasMediaAgent.setCameraAutoFocusArea(area);
} catch (Exception e) {
Log.e(TAG, "operarCameraFocus", e);
}
}
/**
* 获取媒体代理
*
* @return 获取媒体代理
*/
private PnasMediaAgent getPnasMediaAgent() {
MainEngine nMainEngine = App.getAppContext(mContext).getMainEngine();
PnasMediaAgent nPnasMediaAgent = (PnasMediaAgent) nMainEngine
.getUserAgent(PnasEngine.TAG, PnasMediaAgent.TAG);
return nPnasMediaAgent;
}
@Override
public int onAutoFocus(boolean sucessful) {
mHandler.removeMessages(WHAT_RESET_CAMERA_FOCUS);
Log.d(TAG, "sucessful" + sucessful);
Message msg = mHandler.obtainMessage();
msg.what = WHAT_CAMARA_FOCUS_CALLBACK;
msg.obj = sucessful;
mHandler.sendMessage(msg);
return 0;
}
@Override
public int onChangeCamera(int result) {
Log.d(TAG, "onChangeCamera"+result);
if(result==0){
if(mSeekbar!=null){
mSeekbar.setProgress(0) ;
}
}
return 0;
}
public void setPttCallstate(int pttCallstate) {
this.mPttcallState=pttCallstate;
}
}
Activity中如何实现:
简单的界面布局:
<RelativeLayout
android:id="@+id/local_video_view_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<SurfaceView
android:id="@+id/local_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="invisible" />
<RelativeLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="gone" >
RelativeLayout>
RelativeLayout>
在activity中如何实现:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreviewLayout = (ViewGroup) findViewById(R.id.local_video_view_layout);
mPreviewLayout.setVisibility(View.VISIBLE);
initializeGestureRecognizer();
}
protected void initializeGestureRecognizer() {
viewLitener=new ViewOfVideoCallListener(this.getApplicationContext(), mHandler,flag) ;
mGestureRecognizer = new GestureRecognizer(this.getApplication(), viewLitener);
mPreviewLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mGestureRecognizer != null) {
mGestureRecognizer.onTouchEvent(event);
return true;
} else {
return false;
}
}
});
}