当前位置: 首页 > news >正文

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

相关文章:

  • 基于springboot+vue+Mysql的超市进销存系统
  • 【JVM】JVM 运行时数据区简介
  • IntelliJ中的非JVM技术
  • 51单片机学习笔记8 中断系统及定时器
  • 深入解析大语言模型显存占用:训练与推理
  • 【TypeScript】解决字面量类型推断错误的四种方式
  • OM6626一款低功耗蓝牙芯片SOC芯片 -电子价签蓝牙芯片
  • 高阶数据结构 <红黑树>
  • Python学习:函数
  • 【线段树二分】第十三届蓝桥杯省赛C++ A组/研究生组 Python 研究生组《扫描游戏》(C++)
  • 【JVM】JVM简介
  • 【C/C++】奇偶位互换
  • mysql安装及操作
  • SpringMVC基础Controller
  • 鸿蒙(HarmonyOS)Navigation如何实现多场景UI适配?
  • 【前端学习】-粗谈选择器
  • 30天自制操作系统-2
  • Bytom交易说明(账户管理模式)
  • CSS 三角实现
  • Cumulo 的 ClojureScript 模块已经成型
  • Fastjson的基本使用方法大全
  • Python 反序列化安全问题(二)
  • Ruby 2.x 源代码分析:扩展 概述
  • vue自定义指令实现v-tap插件
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 关于 Cirru Editor 存储格式
  • 聊聊flink的BlobWriter
  • 说说动画卡顿的解决方案
  • 译米田引理
  • 鱼骨图 - 如何绘制?
  • 《码出高效》学习笔记与书中错误记录
  • #NOIP 2014#Day.2 T3 解方程
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (七)c52学习之旅-中断
  • (转)程序员疫苗:代码注入
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET与 java通用的3DES加密解密方法
  • @Import注解详解
  • @TableLogic注解说明,以及对增删改查的影响
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [.net] 如何在mail的加入正文显示图片
  • [2021]Zookeeper getAcl命令未授权访问漏洞概述与解决
  • [C++] sqlite3_get_table 的使用
  • [CF226E]Noble Knight's Path
  • [EFI]英特尔 冥王峡谷 NUC8i7HVK 电脑 Hackintosh 黑苹果efi引导文件
  • [EULAR文摘] 利用蛋白组学技术开发一项蛋白评分用于预测TNFi疗效
  • [Foreman]解决Unable to find internal system admin account
  • [hive] sql中distinct的用法和注意事项
  • [IMX6DL] CPU频率调节模式以及降频方法