写点什么

仿微信视频通话大小视图切换(SurfaceView 实现),面试官 6 个灵魂拷问

用户头像
Android架构
关注
发布于: 刚刚

}


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


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


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();

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
仿微信视频通话大小视图切换(SurfaceView实现),面试官6个灵魂拷问