2012-01-12 36 views
6

我需要開發一個應用程序,其中按鈕是六邊形,並且所有這些按鈕都彼此相鄰放置以創建網格。鑑於我在Android上的經驗,我不知道GridView是否是最好的方法。如果是這樣的話,我怎麼能把六邊形放在一起呢?Android Hexagon Grid

我有這個現在

enter image description here

,使用此佈局main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/gridview" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="0dp" 
    android:verticalSpacing="0dp" 
    android:horizontalSpacing="0dp" 
    android:numColumns="4" 
    android:columnWidth="0dp" 
    android:stretchMode="columnWidth" 
    android:gravity="top" 
/> 

而這正是我試圖得到:

hexagon grid

我需要一些幫助pla ce六邊形在一個固定的結構中相互連接。我一直在玩佈局值,沒有成功。 TableView會是一個更好的方法嗎? 非常感謝

+0

「HexView」視圖從哪裏來? – theomega 2012-01-14 12:25:32

+0

編輯修正後的問題時,我只是將應用程序的名稱與GridView佈局混淆了。謝謝。 – 2012-01-14 12:56:38

+0

查看[this](http://www.gdreflections。com/2011/02/hexagonal-grid-math.html)非常好的文章,也有不錯的Java樣本。你可以調整他們到Android。 – hypercode 2012-01-12 19:50:57

回答

5

下面是一些代碼,我在一個應用程序中使用(它被稱爲「連接3,如果你想發揮它:))。這是一個自定義佈局類,可以在網格中繪製六角形圖像。網格可以是三角形或傾斜的矩形。

該代碼計算每個圖像視圖的邊界(以像素爲單位),然後調用imageView.layout(left,top,right,bottom)來設置計算的邊界。計算並不困難。主要參數是六邊形的radius。由此,總高,總寬度,有效高度和有效寬度(imageview的高度/寬度分別是兩個連續視圖的頂部/左邊界之間的距離)。然後歸結爲一些簡單的循環來繪製它們。

要使視圖可點擊,請在創建視圖時設置一個onClickListener。 (我讓它成爲一個班級成員,因爲它使事情變得更容易)。

onMeasure函數只計算視圖的總寬度和高度,並用這些值調用setMeasuredDimension

用於所有這些的圖像僅僅是您在操作欄下方看到的單個六邊形。請注意,圖像是正方形。

@Override 
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { 
    Log.d(TAG, "board.onlayout called with size "+mSize+" l: "+l+" r: "+r+" t: "+t+" b: "+b); 

    //If the dimensions of the board haven't changed, a redraw isn't necessary. Just update the images of the views instead by calling invalidate(). 
    if (!changed && !mSizeInvalidated) { 
     invalidate(); 
     return; 
    } 
    int childCount = getChildCount(); 

    //Calculate some useful parameters. 
    float radius = getResources().getDimension(R.dimen.radius); 
    float verticalMargin = -radius/4; 
    float horizontalMargin = ((float) Math.sqrt(3)/2 - 1) * radius; 
    float height = 2 * radius; 
    float width = height; 
    float effectiveHeight = height + 2 * verticalMargin; 
    float effectiveWidth = width + 2 * horizontalMargin; 

    float totalHeight=(radius * (3 * mSize + 1))/2; 
    float totalWidth; 
    switch (mGameType) { 
     case Connect3Turn.GAME_TYPE_HEX: 
      totalWidth = (((float) mSize * 3 - 1)/ 2) * ((float) Math.sqrt(3)) * radius; 
      break; 
     case Connect3Turn.GAME_TYPE_Y: 
     default: 
      totalWidth = mSize * ((float) Math.sqrt(3)) * radius; 
    } 

    LayoutParams layoutParams = new LayoutParams((int) width, (int) height); 

    //Code to calculate the offsets for horizontal and vertical centering (this is an option in the .xml file) 
    //The GAME_TYPE_HEX creates a tilted rectangular board and GAME_TYPE_Y creates a triangular board. 
    float x_offset_row; 
    switch (mGameType) { 
     case Connect3Turn.GAME_TYPE_Y: 
      x_offset_row=(mSize - 1) * effectiveWidth/2 + horizontalMargin; 
      break; 
     case Connect3Turn.GAME_TYPE_HEX: 
     default: 
      x_offset_row=0; 
    } 
    switch (mCenterHorizontal) { 
     //the left side of the grid should be at non-negative coordinates. 
     case 1: { 
      x_offset_row += Math.max(0,(r-l-totalWidth)/2); 
      break; 
     } 
     case 2: {x_offset_row += Math.max(0,(r-l-totalWidth)); 
      break; 
     } 
     case 0: 
     default: { 
      break; 
     } 
    } 

    //calculate the y_offset for vertical centering. 
    float y_offset = 0; 
    switch (mCenterVertical) { 
     case 1: { 
      y_offset = Math.max(0, (b - t - totalHeight)/2); 
      break; 
     } 
     case 2: { 
      y_offset = Math.max(0, (b - t -totalHeight)); 
      break; 
     } 
    } 


    int cell = 0; 
    for (int row = 0; row < mSize; ++row) { 
     float x_offset = x_offset_row; 
     int rowLength; 
     //The row length depends on the board-type we want to draw. 
     switch (mGameType){ 
      case Connect3Turn.GAME_TYPE_HEX: 
       rowLength=mSize; 
       break; 
      case Connect3Turn.GAME_TYPE_Y: 
      default: 
       rowLength=row+1; 
     } 
     Log.d(TAG, "Drawing row "+row+" with "+rowLength+" cells."); 
     for (int col = 0; col < rowLength; ++col) { 
      ImageView v; 
      if (cell < childCount) { 
       v = (ImageView) getChildAt(cell); 
      } else { 
       v = new ImageView(super.getContext()); 
       v.setLayoutParams(layoutParams); 
       v.setOnClickListener(onClickListener); 
       addViewInLayout(v, cell, v.getLayoutParams(), true); 
      } 

      //Set the image (color) of the cell and put its index in a tag, so we can retrieve the number of the clicked cell in the onClickListener. 
      v.setImageResource(mImageIds[mImages[cell]]); 
      v.setTag(cell); 

      //Set the bounds of the image, which will automatically be cropped in the available space. 
      v.layout((int) x_offset, (int) y_offset, (int) (x_offset + width), (int) (y_offset + height)); 
      x_offset += effectiveWidth; 
      ++cell; 
     } 
     y_offset += effectiveHeight; 
     //The offset of the next row, relative to this one, again depends on the game type. 
     switch(mGameType){ 
      case Connect3Turn.GAME_TYPE_Y: 
       x_offset_row -= effectiveWidth/2; 
       break; 
      case Connect3Turn.GAME_TYPE_HEX: 
       x_offset_row += effectiveWidth/2; 
     } 
    } 

    //We updated all views, so it is not invalidated anymore. 
    mSizeInvalidated=false; 
} 

hexgrid1 hexgrid2

2

Hexgrid是Github上項目,實現了一個六邊形(十六進制)網格。