如何使用Android仿微信多人音视频通话界面
发表于:2025-02-12 作者:千家信息网编辑
千家信息网最后更新 2025年02月12日,小编给大家分享一下如何使用Android仿微信多人音视频通话界面,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、使用自定
千家信息网最后更新 2025年02月12日如何使用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安全错误
数据库的锁怎样保障安全
macmini m1软件开发
民航网络安全职业技能大赛
阿拉善盟天气预报软件开发
2022年国家网络安全政策方向
邮件服务器 日程安排
数据库的自动收缩怎么设置
海康服务器更改raid模式
大专软件开发能学什么科目
网络安全法宣贯总结
在数据库中表是由什么组成的
国家网络安全宣传周书签
常见的软件开发模型是
管理专用服务器价格
网络安全保密大讨论
贵州it软件开发多少钱
嘉定区专业软件开发电话多少
文件服务器虚拟磁盘
宝的软件开发有限公司
中移动网络安全招标
网络安全的声明
访问数据库出错 sql
广州智能软件开发教程
ftp服务器显示
杭州苹果软件开发多少钱
emby自建破解服务器
未来5年的网络安全行业
互联网科技发展的英语作文
恢复电脑数据库
sql格式如何连接数据库
电脑端向日葵连接服务器失败