前言:最近新项目有个需求,实现蜂巢一样的布局界面。刚看到需求,心里卧槽了下,不过还挺好看的,于是思考了怎么实现。花了两三天时间,终于实现了跟我想要的差不多,封装成了比较容易拓展的使用方式。

需求效果如下:

1.蜂巢类型:

与正常图片切换效果:

下面是实现思路:

怎么实现呢,认真观察,我们会发现其实整个视图单个item是按照这样的规律排布六边形挨着连接,:

所以我们的解决问题就转化为如何按照这样的规律排布。该界面复杂就复杂在一个一正六边形挨着连接,计算六边形的边以及点,显然会比较复杂,为了将问题简单化,我将正六边形转化为正方形,要知道,正六边形可以通过正方形的内切圆绘制出来:

所以这样就很简单了,上面的排布其实转化为正方形的排布了:

所以我们最终实现的思路是这样的: 绘制正方形区域并按照规律排布,在正方形区域绘制出正六边形。

接下来是实现过程

实现正方形按照指定规律排布,第一时间想到的是使用RecyclerView并重写RecyclerView.LayoutManager。关于RecyclerView不懂的请百度。

如何计算正方形排布的坐标,首先,我将一组视图分成了两小组:

为了拓展性,我们可以指定要显示的列数mColumnSize,这样我们就可以计算出第一小组最多显示个数以及第二小组最多显示个数:

int rvwidth = getRecyclerViewWidth();//RecyclerView width

int itemWidth = rvwidth / mColumnSize;//正方形宽度

int itemHeight = itemWidth;

int firstgroupnum = mColumnSize / 2 ;//第一小组最多显示个数

int secondgroupnum = mColumnSize % 2 == 0 ? mColumnSize / 2 : mColumnSize / 2 + 1;//第二组最多显示个数

这样我们可以得到了内切圆半径R:

float r = itemWidth / 2;//内切圆半径

整个组边的计算关系如下图:

我们很容易就得到以下关系:

w = r

fleft = (rvwidth - (itemWidth * firstgroupnum + r * (firstgroupnum - 1))) / 2;//第一组开始偏移量

sright = fleft-itemWidth*3/4;//第二组开始偏移量

通过上面的关系我们很容易就得到了这些正方形的分布坐标。那么开始撸代码了。

为了简单易于理解,封装一下每一组的数据,每一组的数据由两小组数据组成:

private class GroupData{

int itemIndex = 0;

List FirstGroup = new ArrayList<>();

List SecondGroup = new ArrayList<>();

}

private class GroupItem{

Rect rect = null;

int itemindex = 0;

}

这样我们就可以根据第一小组显示的个数与第二小组显示的个数得到划分好的GroupData:

/** 将数据转化为组数据 *@param firstgroupnum 第一小组最多显示个数 *@param secondgroupnum 第二小组最多显示个数 *@return */

private List GetGroupData(int firstgroupnum, int secondgroupnum) {

int groupnums = getItemCount()/(firstgroupnum+secondgroupnum);

if(getItemCount()%(firstgroupnum+secondgroupnum)!=0){

groupnums++;

}

List groupdata = new ArrayList<>();

int ItemIndex = 0;

for(int index = 0;index

GroupData g = new GroupData();

for(int i=0;i

GroupItem item = new GroupItem();

item.itemindex = ItemIndex++;

item.rect = mItemFrames.get(item.itemindex);

g.FirstGroup.add(item);

}

for(int i=0;i

GroupItem item = new GroupItem();

item.itemindex = ItemIndex++;

item.rect = mItemFrames.get(item.itemindex);

g.SecondGroup.add(item);

}

groupdata.add(g);

}

return groupdata;

}

转化为组数据后,计算出上面的边关系:

float fleft = (rvwidth - (itemWidth * firstgroupnum + r * (firstgroupnum - 1))) / 2;//第一组开始偏移量

float firstgroupitemleftposition = 0;//第一组item左边位置

float sright = fleft-itemWidth*3/4;//第二组开始偏移量

float d = (float) (itemHeight / 4 * (2 - Math.sqrt(3)));//六边形到边到内切圆的距离

float secondgroupmarginfirstgroup = (float) itemHeight/2 - d;

float topmargin = 50;

float toppositoion = 0;

然后遍历排布每组的正方形,每组的正方形有两小组,分别遍历排布:

for(int index =0;index

toppositoion = index*itemHeight+topmargin+GROUP_PADDING*index;

toppositoion = toppositoion-d*2*index;

GroupData g = groupDatas.get(index);

for(int firstgroupindex =0;firstgroupindex

int left = (int) (fleft+firstgroupindex*(itemWidth+r));

int top = (int) toppositoion;

int right = left+itemWidth;

int bottom = top+itemHeight;

Rect rect = g.FirstGroup.get(firstgroupindex).rect;

rect.set(left,top,right,bottom);

}

toppositoion = toppositoion+secondgroupmarginfirstgroup+FIRSTGROUP_MARGIN_SECONDGROUP;

for(int secondgroupindex =0;secondgroupindex

int left = (int) (sright+secondgroupindex*(itemWidth+r));

int top = (int) toppositoion;

int right = left+itemWidth;

int bottom = top+itemHeight;

Rect rect = g.SecondGroup.get(secondgroupindex).rect;

rect.set(left,top,right,bottom);

}

}

注意的是,为了方便使用,我们对每组的视图增加了间距,每组的两个小组之间也增加了间距。

public int FIRSTGROUP_MARGIN_SECONDGROUP = 50;//第一小组与第二小组间距

public int GROUP_PADDING = 120;//组距

分布好后,填充视图就是了:

private void fill(RecyclerView.Recycler recycler, RecyclerView.State state) {

if (getItemCount() <= 0 || state.isPreLayout()) {

return;

}

Rect displayRect = new Rect(mHorizontalOffset, mVerticalOffset,

getHorizontalSpace() + mHorizontalOffset,

getVerticalSpace() + mVerticalOffset);

for (int i = 0; i < getItemCount(); i++) {

Rect frame = mItemFrames.get(i);

if (Rect.intersects(displayRect, frame)) {

View scrap = recycler.getViewForPosition(i);

addView(scrap);

measureChildWithMargins(scrap, 0, 0);

layoutDecorated(scrap, frame.left - mHorizontalOffset, frame.top - mVerticalOffset,

frame.right - mHorizontalOffset, frame.bottom - mVerticalOffset);

}

}

}

完成到这里后,我们就可以实现到这样的效果了:

间距为50显示5列的效果:

间距为50显示7列的效果:

剩下的最后一步,就是将正方形图片转化为正六边形而已,具体实现代码,参考我这篇文章:android六边形imageview

最终转化后得到效果如下:

C语言六边形蜂巢数组,android 六边形蜂巢布局控件相关推荐

  1. Android 图片网格布局控件

    Android 图片网格布局控件 项目地址:MultiPictureView MultiPictureView是一个可以将多张图片以网格的方式显示的View,通过简单的接口实现烦人的布局,从此解放你的 ...

  2. 【Android】7.1 布局控件常用的公共属性

    分类:C#.Android.VS2015: 创建日期:2016-02-10 一.简介 Android应用程序中的布局控件都是容器控件,用于控制子元素的排列和放置方式.Android提供的布局控件有: ...

  3. 视频教程-Android Material Design 新控件-Android

    Android Material Design 新控件 刘志远,北京邮电大学硕士研究生, 北京育华志远科技有限公司创始人, 育华志远教育品牌负责人,育华志远课程体系打造者. 率领团队为互联网行业培训千 ...

  4. Android常用酷炫控件(开源项目)github地址汇总

    转载一个很牛逼的控件收集帖... 第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.Gri ...

  5. android什么控件能够输入多行文字,Android开发:文本控件详解——EditText(一)基本属性...

    一.简单实例: EditText输入的文字样式部分的属性,基本都是和TextView中的属性一样. 除此之外,EditText还有自己独有的属性. 二.基本属性: hint 输入框显示的提示文本 te ...

  6. Android 城市选择万能控件

    Android 城市选择万能控件 Android 城市选择万能控件,选择城市,选择汽车品牌等等,支持按照a-z.# 排序等的选择控件,废话不多说直接上效果图: (开的Android模拟器录得gif,有 ...

  7. android侧滑布局,Android布局控件DrawerLayout实现完美侧滑效果

    drawerLayout其实是一个布局控件,跟LinearLayout等控件是一样的,但是drawerLayout带有滑动的功能.只要按照drawerLayout的规定布局方式写完布局,就能有侧滑的效 ...

  8. Android中的基础控件TextView、Button、ImageView、EditText、ProgressBar

    文章目录 1 Android中的基础控件 1.1 控件的通用属性 2 TextView 2.1 TextView的继承关系 2.2 TextView的常用属性 3 EditText 3.1 常用属性 ...

  9. android中的标题栏是什么意思,Android通用标题栏组合控件

    原标题:Android通用标题栏组合控件 快,点击蓝色"字体"关注这个公众号,一起涨姿势 由于项目中经常用到此种组合控件,就封装了下,具体效果看下图,老司机可以绕道哈! 一.主要功 ...

最新文章

  1. 对话创新工场陶宁:AI步入深水区下的投资逻辑
  2. 学会动态丨中国人工智能学会重磅发布《2018人工智能产业创新评估白皮书》
  3. Linux加密和安全
  4. 对比学习系列论文SDCLR(二)-Self-Damaging Contrastive Learning
  5. Java 8 - Stream流骚操作解读2_归约操作
  6. Cookie对象知识总结
  7. tensorflow gpu python3.5_Win10+Anaconda3下tensorflow-gpu环境配置
  8. 「造个轮子」——cicada(轻量级 WEB 框架)
  9. linux修改文件没有备份,归档模式,恢复没有备份的数据文件
  10. 取消搜索状态_百度搜索引擎全网推广通常有哪些账户?
  11. 全系麒麟810+超强夜拍 荣耀9X正式发布:1399元起
  12. 【Machine Learning 三】线性代数回顾:矩阵,矩阵运算,向量,转置
  13. HTML课程表应用,可在PC和Android运行
  14. MYSQL获取自增ID的四种方法
  15. 深度学习-图像数据标注工具使用(LabelImg和BBox)
  16. js 56个民族 数据
  17. 新手程序员进阶必学,Python常用模块及用法汇总(内容较干建议收藏)
  18. 【喜报】利用COOC又发表了多篇一区SCI、SSCI、CSSCI
  19. 用钩子(Hook)屏蔽特殊键
  20. linux启动速度优化

热门文章

  1. C++中WSAAsyncSelect模型的用法例程
  2. Oracle Vm VirtualBox中安装Ubantu
  3. webug3.0下载环境搭建使用
  4. 计算机基础说课 word,计算机基础说课稿
  5. 赛门铁克备份软件服务起不来_软件安全开发服务资质和信息系统灾难备份与恢复服务资质...
  6. python的线性链表_Python线性表——单链表-阿里云开发者社区
  7. 米家zigbee传感器抓包_如果有一代,米家人体传感器2值得你去更换吗?
  8. oracle alter_log,在线查看alter.log文件内容
  9. iconv android 编译,将iconv编译成lua接口
  10. JAVA-基础(查找文件夹内文件)