我自横刀向天笑,去留肝胆两昆仑。这篇文章主要讲述Android技术分享| Android 自定义View多人视频通话控件相关的知识,希望能为你提供帮助。
【android 自定义View】多人视频通话控件
文章图片
*以上图片截自微信等待中界面
等待中界面上图是微信多人视频通话时未接通的界面状态,可见每个人的 View 中大致需包含了以下元素。
- 头像
- 昵称
- Loading View
- 视频 View
- 音频状态 icon
<
merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_
android:background="#2C3033"
tools:parentTag="android.widget.RelativeLayout">
<
!--视频View-->
<
TextureView
android:id="@+id/video_view"
android:layout_
android:layout_>
<
/TextureView>
<
!--头像-->
<
ImageView
android:id="@+id/iv_avatar"
android:src="https://www.songbingjia.com/android/@drawable/avatar"
android:layout_
android:layout_>
<
/ImageView>
<
!--名字-->
<
TextView
android:id="@+id/tv_user_name"
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
tools:text="UserName"
android:background="@android:color/transparent"
android:textColor="@android:color/white"
android:textSize="14sp" />
<
!--音频状态Icon-->
<
ImageView
android:id="@+id/iv_audio_enable"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:src="https://www.songbingjia.com/android/@drawable/mic_enable">
<
/ImageView>
<
!--Loading-->
<
ImageView
android:id="@+id/iv_loading"
android:layout_
android:layout_
android:layout_centerInParent="true"
android:src="https://www.songbingjia.com/android/@drawable/loading">
<
/ImageView>
<
/merge>
GroupUserVideoLayout接着定义自定义View类,GroupUserVideoLayout 添加一些基本的方法。
/**
* 多人视频通话中每个用户的布局
*/
class GroupUserVideoLayout @JvmOverloads constructor(mContext:Context): RelativeLayout(mContext) private var videoView:TextureView
private var ivAvatar:ImageView
private var ivAudio:ImageView
private var tvName:TextView
private var ivLoading:ImageViewinit
val root = LayoutInflater.from(mContext).inflate(R.layout.layout_gv_layout,this)
videoView = root.findViewById(R.id.video_view)
ivAvatar = root.findViewById(R.id.iv_avatar)
ivAudio = root.findViewById(R.id.iv_audio_enable)
tvName = root.findViewById(R.id.tv_user_name)
ivLoading = root.findViewById(R.id.iv_loading)//设置昵称
fun setUserName(userName:String)
tvName.text = userName//设置头像
fun setAvatar(avatarUrl:String)
ivAvatar.loadUrl(avatarUrl)//设置音频图标状态
fun enableAudio(enable:Boolean)
ivAudio.visibility = if (enable) VISIBLE else GONE//设置LoadingView状态
fun setLoadingState(open:Boolean)
ivLoading.visibility = if (open) VISIBLE else GONE
接听后?接听后,对应的设置每个人的头像昵称,去掉 Loading,显示视频。接下来就是要定义多个人进出时,布局的变化了。
- 2个人的时候,左右对齐均分显示
- 3个人的时候品字型显示
- 4个人的时候上下2个均分显示
- 5个人以上则九宫格显示
GroupVideoLayoutManager定义 GroupVideoLayoutManager ,这个是在外部直接使用的,里面应当有查找、添加用户,移除用户,根据人数更新布局位置等功能。
class GroupVideoLayoutManager constructor(mContext: Context): RelativeLayout(mContext) //自己的ID
var selfId:String=""
private val userLayoutList = mutableListOf<
LayoutEntity>
()
private var userCount = 0
private val MAX_USER = 8private val oneUserParamList by lazyLayoutUtils.get1UserParam(mContext,width,height)
private val twoUserParamList by lazyLayoutUtils.get2UserParam(mContext,width,height)
private val threeUserParamList by lazyLayoutUtils.get3UserParam(mContext,width,height)
private val fourUserParamList by lazyLayoutUtils.get4UserParam(mContext,width,height)
private val nineUserParamList by lazyLayoutUtils.get9UserParam(mContext,width,height) /**
* 根据uid 查找对应的View
*/
fun findUser(uid:String):GroupUserVideoLayout?
userLayoutList.findit.userId==uid ?.letlayoutEntity->
layoutEntity.layout?.let
return it
?:let
return null?:let
return null/**
* 根据uid 添加对应的View
*/
fun addUser(uid:String):GroupUserVideoLayout?
if (userCount>
MAX_USER)
return nullval layout = GroupUserVideoLayout(context)
userLayoutList.add(LayoutEntity(layout,uid))
userCount++
post
updateLayout()return layout/**
* 根据uid 移除对应View
*/
fun removeUser(uid:String)
userLayoutList.findit.userId==uid ?.let
userLayoutList.remove(it)
userCount--//更新布局位置
private fun updateLayout()
if (userLayoutList.isNullOrEmpty())
returnval paramsList:ArrayList<
LayoutParams>
when(userCount)
1->
paramsList = oneUserParamList
userLayoutList[0].layout?.layoutParams = paramsList[0]
return2->
paramsList = twoUserParamList3->
paramsList = threeUserParamList4->
paramsList = fourUserParamListelse->
paramsList = nineUserParamListvar layoutIndex = if (selfId.isEmpty()) 0 else 1
userLayoutList.forEach
if (it.userId == selfId)
it.layout?.layoutParams = paramsList[0]
else if (layoutIndex<
paramsList.size)
it.layout?.layoutParams = paramsList[layoutIndex++]private inner class LayoutEntity
var layout: GroupUserVideoLayout? = null
var userId = ""constructor(layout: GroupUserVideoLayout?, userId: String)
this.layout = layout
this.userId = userIdoverride fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
if (widthSize == 0 &
&
heightSize == 0)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val minSize = Math.min(measuredWidth, measuredHeight)
setMeasuredDimension(minSize, minSize)
returnval size: Int
size = if (widthSize == 0 || heightSize == 0)
Math.max(widthSize, heightSize)
else
Math.min(widthSize, heightSize)val newMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY)
super.onMeasure(newMeasureSpec, newMeasureSpec)
?以上就实现了类似微信视频通话界面的自定义View,具体使用效果会在下一期的文章所介绍的demo中体现~敬请期待!
文章图片
【Android技术分享| Android 自定义View多人视频通话控件】?
推荐阅读
- #yyds干货盘点#MySQL学习-为啥有时候事务的隔离没有生效
- vivo全球商城全球化演进之路——多语言解决方案
- HarmonyOS-基于canvas绘制复古钟表
- #yyds干货盘点# 基于STM32+ESP8266+华为云设计的智能家居控制系统
- #yyds干货盘点# 超全面Git知识总结!
- XtraBackup实现MySQL数据库全量+增量+Binlog恢复库
- MyCAT实现MySQL数据库读写分离
- 在linux中如果查看进程,不懂得点进来吧!另外附加了如何静态启动进程!
- Kubernetes集群实践-排错(01)Node节点证书过期