仿微信视频通话大小视图切换(SurfaceView 实现),面试官 6 个灵魂拷问
}
super.onDestroy();
}
/**
播放源
*/
private void play() {
try {
//添加播放视频的路径与配置 MediaPlayer
AssetFileDescriptor fileDescriptor = getResources().openRawResourceFd(R.raw.video4);
mediaPlayer.reset();
//给 mMediaPlayer 添加预览的 SurfaceHolder,将播放器和 SurfaceView 关联起来
mediaPlayer.setDisplay(surfaceviewLocal.getHolder());
mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),
fileDescriptor.getStartOffset(),
fileDescriptor.getLength());
//设置视频输出到 SurfaceView
// mediaPlayer.setDisplay(surfaceviewLocal.getHolder());
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
/**
播放源 2
*/
private void play2() {
try {
//添加播放视频的路径与配置 MediaPlayer
AssetFileDescriptor fileDescriptor = getResources().openRawResourceFd(R.raw.video5);
mediaPlayer2.reset();
//给 mMediaPlayer 添加预览的 SurfaceHolder,将播放器和 SurfaceView 关联起来
mediaPlayer2.setDisplay(surfaceviewRemote.getHolder());
mediaPlayer2.setDataSource(fileDescriptor.getFileDescriptor(),
fileDescriptor.getStartOffset(),
fileDescriptor.getLength());
//设置视频输出到 SurfaceView
// mediaPlayer2.setDisplay(surfaceviewRemote.getHolder());
mediaPlayer2.prepare();
mediaPlayer2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer2.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
/**
暂停 1
*/
private void pause() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
}
/**
暂停 1
*/
private void pause2() {
if (mediaPlayer2.isPlaying()) {
mediaPlayer2.pause();
} else {
mediaPlayer2.start();
}
}
/**
停止
*/
private void stop() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
/**
停止
*/
private void stop2() {
if (mediaPlayer2 != null && mediaPlayer.isPlaying()) {
mediaPlayer2.stop();
mediaPlayer2.release();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.surfaceview_local:
LogUtils.d(" onClick surfaceview_local: " + mSate);
if (mSate) {
zoomOpera(rlLocal, surfaceviewLocal, rlRemote, surfaceviewRemote);
mSate = false;
} else {
changeStatus();
}
break;
case R.id.surfaceview_remote:
LogUtils.d(" onClick surfaceview_remote: " + mSate);
if (!mSate) {
zoomOpera(rlRemote, surfaceviewRemote, rlLocal, surface
viewLocal);
mSate = true;
} else {
changeStatus();
}
break;
default:
break;
}
}
/**
改变转态烂的显示隐藏
*/
protected void changeStatus() {
if (llCallContainer.getVisibility() == View.GONE) {
llCallContainer.setVisibility(View.VISIBLE);
showStatusBar();
postDelayedCloseBtn();
} else {
llCallContainer.setVisibility(View.GONE);
hideStatusBar();
}
}
/**
大小视图切换 (小视图在前面、大视图在后面)
@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);
}
/**
开启取消延时动画
*/
private void postDelayedCloseBtn() {
uiHandler.removeCallbacksAndMessages(null);
uiHandler.postDelayed(new Runnable() {
@Override
public void run() {
llCallContainer.setVisibility(View.GONE);
hideStatusBar();
}
}, 5000);
}
/**
隐藏标题栏
*/
private void hideStatusBar() {
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
getWindow().setAttributes(attrs);
}
/**
显示标题栏
*/
private void showStatusBar() {
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
getWindow().setAttributes(attrs);
}
}
1.2、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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>
1.3、DisplayUtil.java
public class DisplayUtil {
/**
获取屏幕宽度
@param ctx
@return
*/
public static int getScreenWidth(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
/**
获取屏幕高度
@param ctx
@return
*/
public static int getScreenHeight(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
/**
dp 转 px
@param context 上下文
@param dpValue dp 值
@return
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
px 转 dp
@param context 上下文
@param pxValue px 值
@return
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
判断是否是刘海屏
@return
*/
public static boolean hasNotchScreen(Activity activity) {
if (getInt("ro.miui.notch", activity) == 1 || hasNotchAtHuawei(activity) || hasNotchAtOPPO(activity)
|| hasNotchAtVivo(activity) || isAndroidP(activity) != null) { //TODO 各种品牌
return true;
}
return false;
}
/**
Android P 刘海屏判断
@param activity
@return
*/
public static DisplayCutout isAndroidP(Activity activity) {
View decorView = activity.getWindow().getDecorView();
评论