前言
前一段时间做了一个即时通讯的项目,在项目中遇到很多坑,有时间一一做个总结,项目消息发送基于XMPP+Tigase,语言视频通话基于PJSIP+FreeSWITCH,项目UI仿微信。做到视频通话时,遇到本地视图与远程视图切换,网上搜了一篇相关的博客:https://blog.csdn.net/xuedaqian123/article/details/77878781,根据大神思路写了这个Demo,其中用的是第三直播源可能有点不稳定,切换过程可能存在黑屏和无响应的情况,但是用的Pjsip中切换还是很流程的;
布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.demo.surfaceviewdemo.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/rl_remote"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:id="@+id/surfaceview_remote"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_local"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true">
<SurfaceView
android:id="@+id/surfaceview_local"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</RelativeLayout>
<!--通话时显示的-->
<LinearLayout
android:id="@+id/ll_call_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="25dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_call_quiet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="10dp"
android:drawableTop="@mipmap/chat_video_change_voice_img"
android:gravity="center_horizontal"
android:text="切到语音聊天"
android:textColor="#ffffff"
android:textSize="12sp"/>
<TextView
android:id="@+id/tv_handup_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="10dp"
android:drawableTop="@mipmap/chat_video_guaduan_img_normal"
android:gravity="center_horizontal"
android:text="挂断"
android:textColor="#ffffff"
android:textSize="12sp"/>
<TextView
android:id="@+id/tv_change_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="10dp"
android:drawableTop="@mipmap/chat_video_change_camera_img"
android:gravity="center_horizontal"
android:text="转换摄像头"
android:textColor="#ffffff"
android:textSize="12sp"/>
</LinearLayout>
</FrameLayout>
代码
为了实现跟微信一样的效果,普通屏幕全屏显示,为了不让视频内容挤到刘海屏中,添加一下代码:
//如果判断有刘海屏不让填充到状态栏
if (DisplayUtil.hasNotchScreen(this)) {
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
} else {
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
大小视图切换代码:
/**
* 大小视图切换 (小视图在前面、大视图在后面)
*
* @param sourcView 之前相对布局大小
* @param beforeview 之前surfaceview
* @param detView 之后相对布局大小
* @param afterview 之后surfaceview
*/
private void zoomOpera(View sourcView, SurfaceView beforeview,
View detView, SurfaceView afterview) {
RelativeLayout paretview = (RelativeLayout) sourcView.getParent();
paretview.removeView(detView);
paretview.removeView(sourcView);
//设置远程大视图RelativeLayout 的属性
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
params1.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
beforeview.setZOrderMediaOverlay(true);
beforeview.getHolder().setFormat(PixelFormat.TRANSPARENT);
sourcView.setLayoutParams(params1);
//设置本地小视图RelativeLayout 的属性
params1 = new RelativeLayout.LayoutParams(defaultLocalwidth, defaultLocalHeight);
params1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
params1.setMargins(0, defaultLocalMargin, defaultLocalMargin, 0);
//在调用setZOrderOnTop(true)之后调用了setZOrderMediaOverlay(true) 遮挡问题
afterview.setZOrderOnTop(true);
afterview.setZOrderMediaOverlay(true);
afterview.getHolder().setFormat(PixelFormat.TRANSPARENT);
detView.setLayoutParams(params1);
paretview.addView(sourcView);
paretview.addView(detView);
}