效果如下:

自定义view的源码

public class NineGridImageView<T> extends ViewGroup {private int mRowCount;//行数private int mColumnCount;//列数private int mMaxSize = 9;private int mGap;//宫格间距private int mWidth;//当前组件宽度private int mHeight;//当前组件高度/* private Paint mBGPaint;private Paint mPathPaint;private Paint mFaceRectPaint;private Paint mFaceRoundPaint;private Rect mFaceRect;private Rect mFaceDetectRect;public static final int COLOR_BG = Color.parseColor("#FFFFFF");public static final int COLOR_RECT = Color.parseColor("#FFFFFF");public static final int COLOR_ROUND = Color.parseColor("#FFFFFF");*/private List<ImageView> mImageViewList = new ArrayList<>();private List<T> mImgDataList;private NineGridImageViewAdapter<T> mAdapter;public NineGridImageView(Context context) {super(context, null);}public NineGridImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public NineGridImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NineGridImageView);this.mGap = (int) typedArray.getDimension(R.styleable.NineGridImageView_imgGap, 8);typedArray.recycle();}/*** 设置控件的宽高*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = measureWidth(widthMeasureSpec);mHeight = measureHeight(heightMeasureSpec);setMeasuredDimension(mWidth, mHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {layoutChildrenView();}private int measureWidth(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {result = 200;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}private int measureHeight(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {result = 200;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}/*** 为子ImageView布局*/private void layoutChildrenView() {if (mImgDataList == null) {return;}int childrenCount = mImgDataList.size();for (int i = 0; i < childrenCount; i++) {ImageView childrenView = (ImageView) getChildAt(i);if (mAdapter != null) {mAdapter.onDisplayImage(getContext(), childrenView, mImgDataList.get(i));}int rowNum = i / mColumnCount;//当前行数int columnNum = i % mColumnCount;//当前列数int mImageSize = (mWidth - (mColumnCount + 1) * mGap) / mColumnCount;//图片心坟int t_center = (mHeight + mGap) / 2;//中间置以下的顶点(有宫格间距)int b_center = (mHeight - mGap) / 2;//中间位置以上的底部(有宫格间距)int l_center = (mWidth + mGap) / 2;//中间位置以右的左部(有宫格间距)int r_center = (mWidth - mGap) / 2;//中间位置以左的右部(有宫格间距)int center = (mHeight - mImageSize) / 2;//中间位置以上顶部(无宫格间距)int left = mImageSize * columnNum + mGap * (columnNum + 1);int top = mImageSize * rowNum + mGap * (rowNum + 1);int right = left + mImageSize;int bottom = top + mImageSize;/*** 不同子view情况下的不同显示*/if (childrenCount == 1) {childrenView.layout(left, top, right, bottom);} else if (childrenCount == 2) {childrenView.layout(left, center, right, center + mImageSize);} else if (childrenCount == 3) {if (i == 0) {childrenView.layout(center, top, center + mImageSize, bottom);} else {childrenView.layout(mGap * i + mImageSize * (i - 1), t_center, mGap * i + mImageSize * i, t_center + mImageSize);}} else if (childrenCount == 4) {childrenView.layout(left, top, right, bottom);} else if (childrenCount == 5) {if (i == 0) {childrenView.layout(r_center - mImageSize, r_center - mImageSize, r_center, r_center);} else if (i == 1) {childrenView.layout(l_center, r_center - mImageSize, l_center + mImageSize, r_center);} else {childrenView.layout(mGap * (i - 1) + mImageSize * (i - 2), t_center, mGap * (i - 1) + mImageSize * (i - 1), t_center + mImageSize);}} else if (childrenCount == 6) {if (i < 3) {childrenView.layout(mGap * (i + 1) + mImageSize * i, b_center - mImageSize, mGap * (i + 1) + mImageSize * (i + 1), b_center);} else {childrenView.layout(mGap * (i - 2) + mImageSize * (i - 3), t_center, mGap * (i - 2) + mImageSize * (i - 2), t_center + mImageSize);}} else if (childrenCount == 7) {if (i == 0) {childrenView.layout(center, mGap, center + mImageSize, mGap + mImageSize);} else if (i > 0 && i < 4) {childrenView.layout(mGap * i + mImageSize * (i - 1), center, mGap * i + mImageSize * i, center + mImageSize);} else {childrenView.layout(mGap * (i - 3) + mImageSize * (i - 4), t_center + mImageSize / 2, mGap * (i - 3) + mImageSize * (i - 3), t_center + mImageSize / 2 + mImageSize);}} else if (childrenCount == 8) {if (i == 0) {childrenView.layout(r_center - mImageSize, mGap, r_center, mGap + mImageSize);} else if (i == 1) {childrenView.layout(l_center, mGap, l_center + mImageSize, mGap + mImageSize);} else if (i > 1 && i < 5) {childrenView.layout(mGap * (i - 1) + mImageSize * (i - 2), center, mGap * (i - 1) + mImageSize * (i - 1), center + mImageSize);} else {childrenView.layout(mGap * (i - 4) + mImageSize * (i - 5), t_center + mImageSize / 2, mGap * (i - 4) + mImageSize * (i - 4), t_center + mImageSize / 2 + mImageSize);}} else if (childrenCount == 9) {childrenView.layout(left, top, right, bottom);}}}/*** 设置图片数据** @param data 图片数据集合*/public void setImagesData(List data) {if (data == null || data.isEmpty()) {this.setVisibility(GONE);return;} else {this.setVisibility(VISIBLE);}if (mMaxSize > 0 && data.size() > mMaxSize) {data = data.subList(0, mMaxSize);}int[] gridParam = calulateGridParam(data.size());mRowCount = gridParam[0];mColumnCount = gridParam[1];if (mImgDataList == null) {int i = 0;while (i < data.size()) {ImageView iv = getImageView(i);if (iv == null) {return;}addView(iv, generateDefaultLayoutParams());i++;}} else {int oldViewCount = mImgDataList.size();int newViewCount = data.size();if (oldViewCount > newViewCount) {removeViews(newViewCount, oldViewCount - newViewCount);} else if (oldViewCount < newViewCount) {for (int i = oldViewCount; i < newViewCount; i++) {ImageView iv = getImageView(i);if (iv == null) {return;}addView(iv, generateDefaultLayoutParams());}}}mImgDataList = data;requestLayout();}/*** 设置适配器** @param adapter 适配器*/public void setAdapter(NineGridImageViewAdapter adapter) {mAdapter = adapter;}/*** 设置宫格间距** @param gap 宫格间距 px*/public void setGap(int gap) {mGap = gap;}/*** 设置宫格参数** @param imagesSize 图片数量* @return 宫格参数 gridParam[0] 宫格行数 gridParam[1] 宫格列数*/private static int[] calulateGridParam(int imagesSize) {int[] gridParam = new int[2];if (imagesSize < 3) {gridParam[0] = 1;gridParam[1] = imagesSize;} else if (imagesSize <= 4) {gridParam[0] = 2;gridParam[1] = 2;} else {gridParam[0] = imagesSize / 3 + (imagesSize % 3 == 0 ? 0 : 1);gridParam[1] = 3;}return gridParam;}/*** 获得 ImageView* 保证了ImageView的重用** @param position 位置*/private ImageView getImageView(final int position) {if (position < mImageViewList.size()) {return mImageViewList.get(position);} else {if (mAdapter != null) {ImageView imageView = mAdapter.generateImageView(getContext());mImageViewList.add(imageView);return imageView;} else {Log.e("NineGridImageView", "你必须为NineGridImageView设置NineGridImageViewAdapter");return null;}}}
}
<declare-styleable name="LQRNineGridImageView"><attr format="dimension" name="imgGap"/></declare-styleable>
public abstract class NineGridImageViewAdapter<T> {/*** 重写该方法,使用任意第三方图片加载工具加载图片* @param context* @param imageView* @param t*/protected abstract void onDisplayImage(Context context, ImageView imageView, T t);/*** 重写该方法自定义生成ImageView方式,用于九宫格头像中的一个个图片控件,可以设置ScaleType等属性*/protected ImageView generateImageView(Context context) {ImageView imageView = new ImageView(context);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);return imageView;}}

如何使用:

 <com.chuanglan.flashchat.nine.NineGridImageViewandroid:id="@+id/group_header"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/gray9"android:scaleType="centerCrop" />
 binding.groupHeader.setAdapter(mNineGridAdapter);//设置图片地址listbinding.groupHeader.setImagesData(groupChatBean.getHeadImgList());

仿微信九宫格群聊view相关推荐

  1. 高仿微信发起群聊添加联系人界面

    微信中发起群聊页面,每点击一个item(联系人),左上角就会添加上相应的联系人,再次点击就会取消选中,点击上面已选中的联系人也会取消选中,而且上面的联系人展示中会慢慢挤压右边的搜索框,直到右边有一定的 ...

  2. Android 仿微信添加群聊界面——addView

    仿微信添加群聊界面--addView 转载于:https://www.cnblogs.com/zhujiabin/p/5916746.html

  3. Android仿微信发起群聊的列表样式

    场景:今天一个朋友微信找我说碰到个问题让我看下,就是仿微信发起群聊的那个列表样式,其实这个功能实现起来没什么困难的地方,但是他遇到的问题是,最后的那个"搜索",随着前边列表的增加或 ...

  4. 仿微信 发起群聊 类似样式

    前段时间项目中有用到类似像微信发起群聊的功能,现在整理了出来 分享给大家 效果图如下: 选中后 添加到下面的选择栏中 ,点击选择栏中已选择的 就取消选择 简单说下思路: 自定义HorizontalSc ...

  5. Swift——仿微信发起群聊悬浮框实现

    效果 声明:原作者为 TSWeChat,这里只是记录笔者移植到自己项目中使用的过程. 安装 pod添加依赖: pod 'Dollar', '9.0.0' # 操作数组的神器,比如将数组划分成若干个子集 ...

  6. Android仿微信视频群聊,Android 仿钉钉、微信 群聊组合头像

    功能生成类似钉钉.微信 群聊组合头像Bitmap 可使用图片资源id.bitmap或者使用url从网络加载,传入对应数组即可 网络加载时支持线程池 支持磁盘缓存.内存缓存.(记得申请磁盘缓存需要的文件 ...

  7. native聊天界面 react_ReactNative 聊天 App 实战|RN 仿微信界面群聊|朋友圈

    前言 这次要给大家分享的是基于ReactNative开发的聊天APP实战项目RN_ChatRomm,运用react-native+react-navigation+react-redux+react- ...

  8. java模仿微信QQ群聊头像拼接,根据群聊内的用户头像拼接群聊头像,九宫格

    java模仿微信QQ群聊头像拼接,根据群聊内的用户头像拼接群聊头像,九宫格 效果图,这里只放了几张,1-9张图片都可以的,如果图片路径是从数据库查出来的相对路径,记得加上绝对路径否则会报找不到读取文件 ...

  9. 仿微信的群组九宫格头像

    仿微信的群组九宫格头像 github地址:WeChatGroupAvatar 优点: 使用Bitmap合成的方式,而非九宫格里面具有九张图片.这样子的好处是对于图片加载不会出现一张张图片依次出现,刷新 ...

最新文章

  1. 报名啦!阿里云智能客服对话式AI算法大赛之知识图谱构建与问答
  2. map传参上下文赋值的问题
  3. 20155313 2016-2017-2 《Java程序设计》第三周学习总结
  4. 用python处理excel的基本语法_《使用python3读取处理excel表的数据内容如何对内容求平均值》 用python读取excel文件...
  5. C语言不调用库函数画一个三角形
  6. matlab从矩阵中取rp开头文件,matlab trainrp
  7. bzoj3631: [JLOI2014]松鼠的新家
  8. Dubbo学习总结(7)——Dubbo不常用功能总结
  9. php功能代码下载,PHP实现下载功能的代码
  10. 使用本地计划任务定时关闭azure虚拟机
  11. MySQL常用SQL总结
  12. c语言如何调用三个子程序,哪位师傅知道51单片机怎样编写子程序?C语言的。在主程序里调...
  13. 一个特别好用的免费json数据API接口--特别推荐
  14. 居住证服务器维护需要多长时间,居住证正在制证要多久能拿到
  15. Html炫酷代码例程
  16. 内置平头哥玄铁的WiFi和蓝牙芯片
  17. 英语口语收集(三十七)
  18. PostgreSQL 13新特性:fetch first with ties
  19. java的栈区 堆区存放什么_简单整理java中的栈内存, 堆内存是什么?
  20. Unity 4.6.2 iOS 64位支持

热门文章

  1. win7 64位利用eclipse搭建android开发环境教程
  2. QPixmap显示图片
  3. 二进制图片转换成BMP位图(C++)
  4. html 关闭当前tab页面,js关闭浏览器的tab页(兼容)
  5. 【你觉得这些技术值多少钱?】
  6. 程序员为什么要学算法?
  7. powerpoint预览_如何添加,删除和重新排列PowerPoint幻灯片
  8. 内部系统自己搭建还是花钱购买?这是一个问题
  9. 软件测试价值观-SMBT新理念
  10. atcod D - Staircase Sequences