日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言六边形蜂巢数组,android 六边形蜂巢布局控件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言:最近新項(xiàng)目有個(gè)需求,實(shí)現(xiàn)蜂巢一樣的布局界面。剛看到需求,心里臥槽了下,不過還挺好看的,于是思考了怎么實(shí)現(xiàn)。花了兩三天時(shí)間,終于實(shí)現(xiàn)了跟我想要的差不多,封裝成了比較容易拓展的使用方式。

需求效果如下:

1.蜂巢類型:

與正常圖片切換效果:

下面是實(shí)現(xiàn)思路:

怎么實(shí)現(xiàn)呢,認(rèn)真觀察,我們會(huì)發(fā)現(xiàn)其實(shí)整個(gè)視圖單個(gè)item是按照這樣的規(guī)律排布六邊形挨著連接,:

所以我們的解決問題就轉(zhuǎn)化為如何按照這樣的規(guī)律排布。該界面復(fù)雜就復(fù)雜在一個(gè)一正六邊形挨著連接,計(jì)算六邊形的邊以及點(diǎn),顯然會(huì)比較復(fù)雜,為了將問題簡單化,我將正六邊形轉(zhuǎn)化為正方形,要知道,正六邊形可以通過正方形的內(nèi)切圓繪制出來:

所以這樣就很簡單了,上面的排布其實(shí)轉(zhuǎn)化為正方形的排布了:

所以我們最終實(shí)現(xiàn)的思路是這樣的: 繪制正方形區(qū)域并按照規(guī)律排布,在正方形區(qū)域繪制出正六邊形。

接下來是實(shí)現(xiàn)過程

實(shí)現(xiàn)正方形按照指定規(guī)律排布,第一時(shí)間想到的是使用RecyclerView并重寫RecyclerView.LayoutManager。關(guān)于RecyclerView不懂的請(qǐng)百度。

如何計(jì)算正方形排布的坐標(biāo),首先,我將一組視圖分成了兩小組:

為了拓展性,我們可以指定要顯示的列數(shù)mColumnSize,這樣我們就可以計(jì)算出第一小組最多顯示個(gè)數(shù)以及第二小組最多顯示個(gè)數(shù):

int rvwidth = getRecyclerViewWidth();//RecyclerView width

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

int itemHeight = itemWidth;

int firstgroupnum = mColumnSize / 2 ;//第一小組最多顯示個(gè)數(shù)

int secondgroupnum = mColumnSize % 2 == 0 ? mColumnSize / 2 : mColumnSize / 2 + 1;//第二組最多顯示個(gè)數(shù)

這樣我們可以得到了內(nèi)切圓半徑R:

float r = itemWidth / 2;//內(nèi)切圓半徑

整個(gè)組邊的計(jì)算關(guān)系如下圖:

我們很容易就得到以下關(guān)系:

w = r

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

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

通過上面的關(guān)系我們很容易就得到了這些正方形的分布坐標(biāo)。那么開始擼代碼了。

為了簡單易于理解,封裝一下每一組的數(shù)據(jù),每一組的數(shù)據(jù)由兩小組數(shù)據(jù)組成:

private class GroupData{

int itemIndex = 0;

List FirstGroup = new ArrayList<>();

List SecondGroup = new ArrayList<>();

}

private class GroupItem{

Rect rect = null;

int itemindex = 0;

}

這樣我們就可以根據(jù)第一小組顯示的個(gè)數(shù)與第二小組顯示的個(gè)數(shù)得到劃分好的GroupData:

/** 將數(shù)據(jù)轉(zhuǎn)化為組數(shù)據(jù) *@param firstgroupnum 第一小組最多顯示個(gè)數(shù) *@param secondgroupnum 第二小組最多顯示個(gè)數(shù) *@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;

}

轉(zhuǎn)化為組數(shù)據(jù)后,計(jì)算出上面的邊關(guān)系:

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)));//六邊形到邊到內(nèi)切圓的距離

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);

}

}

注意的是,為了方便使用,我們對(duì)每組的視圖增加了間距,每組的兩個(gè)小組之間也增加了間距。

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);

}

}

}

完成到這里后,我們就可以實(shí)現(xiàn)到這樣的效果了:

間距為50顯示5列的效果:

間距為50顯示7列的效果:

剩下的最后一步,就是將正方形圖片轉(zhuǎn)化為正六邊形而已,具體實(shí)現(xiàn)代碼,參考我這篇文章:android六邊形imageview

最終轉(zhuǎn)化后得到效果如下:

總結(jié)

以上是生活随笔為你收集整理的C语言六边形蜂巢数组,android 六边形蜂巢布局控件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。