千家信息网

如何使用Android仿微信多人音视频通话界面

发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,小编给大家分享一下如何使用Android仿微信多人音视频通话界面,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、使用自定
千家信息网最后更新 2025年11月07日如何使用Android仿微信多人音视频通话界面

小编给大家分享一下如何使用Android仿微信多人音视频通话界面,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1、使用自定义ViewGroup方式实现

下面是三个人通话时候的效果,其他的可以参考微信多人音视频通话界面。

package com.dnaer.android.telephone.widgets;import android.content.Context;import android.os.Build;import android.support.annotation.RequiresApi;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import com.anbetter.log.MLog;public class MultiVideoChatLayout extends ViewGroup implements CommLayoutAdapter.OnDataChangedListener { private CommLayoutAdapter mCommLayoutAdapter; private int mScreenWidth; //人数为2,3,4状态下的宽高度 private int mSizeModel1; //人数为5,6,7,8,9状态下的宽高度 private int mSizeModel2; public MultiVideoChatLayout(Context context) { this(context, null); } public MultiVideoChatLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MultiVideoChatLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(context); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MultiVideoChatLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initialize(context); } private void initialize(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics metrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); mScreenWidth = metrics.widthPixels; mSizeModel1 = mScreenWidth / 2; mSizeModel2 = mScreenWidth / 3; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //宽度默认给屏幕的宽度,高度直接取宽度,形成一个正方形 final int width = MeasureSpec.makeMeasureSpec(mScreenWidth, MeasureSpec.EXACTLY); final int height = MeasureSpec.makeMeasureSpec(mScreenWidth, MeasureSpec.EXACTLY); setMeasuredDimension(width, height); MLog.d("width: " + width + ", height:" + height); final int childWidth = MeasureSpec.makeMeasureSpec(mScreenWidth / 3, MeasureSpec.EXACTLY); final int childHeight = MeasureSpec.makeMeasureSpec(mScreenWidth / 3, MeasureSpec.EXACTLY); final int childWidth3 = MeasureSpec.makeMeasureSpec(mScreenWidth / 2, MeasureSpec.EXACTLY); final int childHeight2 = MeasureSpec.makeMeasureSpec(mScreenWidth / 2, MeasureSpec.EXACTLY); if (getChildCount() > 4) {  for (int i = 0; i < getChildCount(); i++) {  View child = getChildAt(i);  child.measure(childWidth, childHeight);  } } else {  for (int i = 0; i < getChildCount(); i++) {  View child = getChildAt(i);  child.measure(childWidth3, childHeight2);  } } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (getChildCount() <= 4) {  layoutModel1(); } else {  layoutModel2(); } } private void layoutModel2() { int currentWidth = 0; for (int i = 0; i < getChildCount(); i++) {  View item = getChildAt(i);  if (i % 3 == 0) {  currentWidth = 0;  item.layout(0, i / 3 * mSizeModel2, mSizeModel2, i / 3 * mSizeModel2 + mSizeModel2);  } else {  item.layout(currentWidth + mSizeModel2, i / 3 * mSizeModel2, currentWidth + 2 * mSizeModel2, i / 3 * mSizeModel2 + mSizeModel2);  currentWidth = currentWidth + mSizeModel2;  } } } private void layoutModel1() { if (getChildCount() == 3) {  for (int i = 0; i < getChildCount(); i++) {  View item = getChildAt(i);  MLog.d("width: " + item.getMeasuredWidth() + ", height: " + item.getMeasuredHeight() + ", mSizeModel1: " + mSizeModel1);  if (i == 0) {   item.layout(0, 0, mSizeModel1, mSizeModel1);  } else if (i == 1) {   item.layout(mSizeModel1, 0, mSizeModel1 * 2, mSizeModel1);  } else if (i == 2) {   item.layout(mSizeModel1 / 2, mSizeModel1, mSizeModel1 + mSizeModel1 / 2, mSizeModel1 * 2);  }  } } else {  for (int i = 0; i < getChildCount(); i++) {  View item = getChildAt(i);  if (i % 2 == 0) {   item.layout(0, i / 2 * mSizeModel1, mSizeModel1, i / 2 * mSizeModel1 + mSizeModel1);  } else {   item.layout(mSizeModel1, i / 2 * mSizeModel1, 2 * mSizeModel1, i / 2 * mSizeModel1 + mSizeModel1);  }  } } } public void setAdapter(CommLayoutAdapter adapter) { mCommLayoutAdapter = adapter; mCommLayoutAdapter.setOnDataChangedListener(this); changedAdapter(); } @Override public void onChanged() { changedAdapter(); } private void changedAdapter() { removeAllViews(); CommLayoutAdapter layoutAdapter = mCommLayoutAdapter; for (int i = 0; i < layoutAdapter.getCount(); i++) {  View view = layoutAdapter.getView(this, i, layoutAdapter.getItem(i));  view.setDuplicateParentStateEnabled(true);  addView(view); } }}

2、使用自定义LayoutManager方式实现

package org.fireking.customgridlayoutmanagerimport android.content.res.Resourcesimport android.support.v7.widget.RecyclerViewimport java.lang.IllegalArgumentExceptionclass MultiChatLayoutManager : RecyclerView.LayoutManager() { private var leftMargin = 0 private var rightMargin = 0 private var mScreenWidth = 0 override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT) } override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) { super.onLayoutChildren(recycler, state) if (itemCount == 0) {  detachAndScrapAttachedViews(recycler!!)  return } if (childCount == 0 && state!!.isPreLayout) {  return } val params = recycler!!.getViewForPosition(0).layoutParams as RecyclerView.LayoutParams leftMargin = params.leftMargin rightMargin = params.rightMargin detachAndScrapAttachedViews(recycler) layoutItem(recycler) } private fun layoutItem(recycler: RecyclerView.Recycler) { if (itemCount > 9) {  throw IllegalArgumentException("${javaClass.simpleName}最多支持9个item布局, 请检查你的item个数是否正确") } mScreenWidth = Resources.getSystem().displayMetrics.widthPixels val itemSize = if (itemCount > 4) {  mScreenWidth / 3 } else {  mScreenWidth / 2 } if (itemCount <= 4) {  if (itemCount == 3) {  for (i in 0 until itemCount) {   val view = recycler.getViewForPosition(i)   addView(view) // 因为detach过所以重新添加   measureChildWithMargins(view, 0, 0)   when (i) {   0 -> layoutDecoratedWithMargins(view, 0, 0, itemSize, itemSize)   1 -> layoutDecoratedWithMargins(view, itemSize, 0, itemSize * 2, itemSize)   else -> layoutDecoratedWithMargins(    view,    itemSize / 2,    itemSize,    itemSize + itemSize / 2,    itemSize * 2   )   }  }  } else {  for (i in 0 until itemCount) {   val view = recycler.getViewForPosition(i)   addView(view) // 因为detach过所以重新添加   measureChildWithMargins(view, 0, 0)   if (i % 2 == 0) {   layoutDecoratedWithMargins(view, 0, i / 2 * itemSize, itemSize, i / 2 * itemSize + itemSize)   } else {   layoutDecoratedWithMargins(    view,    itemSize,    i / 2 * itemSize,    2 * itemSize,    i / 2 * itemSize + itemSize   )   }  }  } } else {  var currentWidth = 0  for (i in 0 until itemCount) {  val view = recycler.getViewForPosition(i)  addView(view) // 因为detach过所以重新添加  measureChildWithMargins(view, 0, 0)  if (i % 3 == 0) {   currentWidth = 0   layoutDecoratedWithMargins(view, 0, i / 3 * itemSize, itemSize, i / 3 * itemSize + itemSize)  } else {   layoutDecoratedWithMargins(   view,   currentWidth + itemSize,   i / 3 * itemSize,   currentWidth + 2 * itemSize,   i / 3 * itemSize + itemSize   )   currentWidth += itemSize  }  } } } //因为这个布局不需要有滚动,所以直接将横竖两个方向的滚动全部取消了 override fun canScrollHorizontally(): Boolean { return false } override fun canScrollVertically(): Boolean { return false }}

以上是"如何使用Android仿微信多人音视频通话界面"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

多人 界面 音视 宽度 篇文章 高度 人数 内容 布局 方式 状态 参考 不怎么 两个 个人 个数 大部分 屏幕 效果 方向 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 千锋网络安全软件百度云 服务器查看日志 北京软件开发者网站推荐 全球领先网络安全大脑 我的世界怎么加服务器光影材质包 大数据库应用技术的发展前景 通过源码怎么扫描数据库 万得宏观数据库提取量限制 购买网络安全知识宣传小册子 公安网络安全处理的时间 网关与服务器通讯测试指标 服务器备件管理软件 数据库系统安全性问题 河北网络安全公约 服务器被打ip怎么办 手机怎么可以看到网络安全秘钥 薪启程软件开发时间 数据库表一个字段改名 东台辉之悦网络技术服务中心 安全策略数据库spd 嘉兴云网络技术包括什么 ceic数据库 大连理工 大余软件开发项目管理 设计一个数据库加密系统难吗 普陀区市场软件开发质量 网关与服务器通讯测试指标 杭州潘达网络技术有限公司 软件开发公司是怎样运作的 rose数据库怎么画 雷州市网络安全和信息化委员会
0