Android仿微信视频聊天本地与远程切换功能

2024-03-22 09:52

本文主要是介绍Android仿微信视频聊天本地与远程切换功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、xml布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/coordinatorLayout"android:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"android:background="@color/pageBgColor"android:orientation="vertical"><!--  视频预览 --><csu.xiaoya.robotApp.ui.activity.homepage.familydct.bean.DraggableTextureViewandroid:id="@+id/preview"android:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintLeft_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><!--  远程视频 --><csu.xiaoya.robotApp.ui.activity.homepage.familydct.bean.DraggableTextureViewandroid:id="@+id/remoteUserView"android:layout_width="150dp"android:layout_height="180dp"android:layout_marginTop="30dp"android:layout_marginRight="30dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintLeft_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><ImageViewandroid:id="@+id/imHead"android:layout_width="@dimen/dp_120"android:layout_height="@dimen/dp_120"android:layout_gravity="center"android:layout_marginBottom="@dimen/dp_100"android:scaleType="centerCrop"android:src="@mipmap/doctor_head"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><ImageViewandroid:id="@+id/changeVideoWindows"android:layout_width="@dimen/dp_30"android:layout_height="@dimen/dp_30"android:layout_marginLeft="@dimen/dp_30"android:layout_marginTop="@dimen/dp_30"android:background="@drawable/change_windows"android:src="@mipmap/video_windows_change"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

  二、切换代码

 /*** 通话大小* 窗口切换*/private boolean isLocalVideoSmallState = true;private void switchWindowMode(VideoChatDialog videoChatDialog, boolean isLocalVideoSmall) {ConstraintLayout constraintLayout = videoChatDialog.findViewById(R.id.coordinatorLayout);TextureView localVideoTextureView = videoChatDialog.findViewById(R.id.preview);TextureView remoteVideoTextureView = videoChatDialog.findViewById(R.id.remoteUserView);ImageView changeVideoWindows = videoChatDialog.findViewById(R.id.changeVideoWindows);ConstraintSet constraintSet = new ConstraintSet();constraintSet.clone(constraintLayout);if (isLocalVideoSmall) {constraintLayout.removeView(localVideoTextureView);constraintLayout.removeView(remoteVideoTextureView);constraintLayout.removeView(changeVideoWindows);constraintLayout.addView(remoteVideoTextureView);constraintLayout.addView(localVideoTextureView);constraintLayout.addView(changeVideoWindows);// 远程端全屏模式remoteVideoTextureView.setEnabled(false);constraintSet.clear(remoteVideoTextureView.getId());constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 0);constraintSet.constrainWidth(remoteVideoTextureView.getId(), 1280);constraintSet.constrainHeight(remoteVideoTextureView.getId(), 800);// 本地小窗口localVideoTextureView.setEnabled(true);constraintSet.clear(localVideoTextureView.getId());constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 30);constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 30);constraintSet.constrainWidth(localVideoTextureView.getId(), 300); // 设置小窗口的宽度constraintSet.constrainHeight(localVideoTextureView.getId(), 200);isLocalVideoSmallState = false;} else {constraintLayout.removeView(remoteVideoTextureView);constraintLayout.removeView(localVideoTextureView);constraintLayout.removeView(changeVideoWindows);constraintLayout.addView(localVideoTextureView);constraintLayout.addView(remoteVideoTextureView);constraintLayout.addView(changeVideoWindows);// 本地 全屏模式localVideoTextureView.setEnabled(false);constraintSet.clear(localVideoTextureView.getId());constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);constraintSet.connect(localVideoTextureView.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 0);constraintSet.constrainWidth(localVideoTextureView.getId(), 1280);constraintSet.constrainHeight(localVideoTextureView.getId(), 800);// 远程 小窗口remoteVideoTextureView.setEnabled(true);constraintSet.clear(remoteVideoTextureView.getId());constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 30);constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);constraintSet.connect(remoteVideoTextureView.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 30);constraintSet.constrainWidth(remoteVideoTextureView.getId(), 300); // 设置小窗口的宽度constraintSet.constrainHeight(remoteVideoTextureView.getId(), 200);isLocalVideoSmallState = true;}constraintSet.applyTo(constraintLayout);}

三、自定义可拖拽TextureView 

/*** 自定义可拖动* TextureView*/public class DraggableTextureView extends TextureView {private float lastX;private float lastY;private boolean isDragging;public DraggableTextureView(Context context) {super(context);init();}public DraggableTextureView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public DraggableTextureView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:lastX = event.getRawX();lastY = event.getRawY();isDragging = true;break;case MotionEvent.ACTION_MOVE:if (isDragging) {float dx = event.getRawX() - lastX;float dy = event.getRawY() - lastY;int newLeft = (int) (v.getLeft() + dx);int newTop = (int) (v.getTop() + dy);int newRight = (int) (v.getRight() + dx);int newBottom = (int) (v.getBottom() + dy);v.layout(newLeft, newTop, newRight, newBottom);lastX = event.getRawX();lastY = event.getRawY();}break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:isDragging = false;break;}return true;}});}}

这篇关于Android仿微信视频聊天本地与远程切换功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/835068

相关文章

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的