2012-01-12 44 views
6

Tôi cần phát triển một ứng dụng trong đó các nút là hình lục giác và tất cả chúng được đặt cạnh nhau tạo lưới. Với kinh nghiệm nhỏ của tôi trong Android, tôi tự hỏi nếu GridView là cách tiếp cận tốt nhất cho việc này. Nếu đó là trường hợp, làm thế nào tôi có thể đặt các hình lục giác cạnh nhau?Lưới hình lục giác Android

Tôi có điều này bởi hiện nay

enter image description here

Sử dụng bố cục này trong 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" 
/> 

Và đây là những gì tôi đang cố gắng để có được:

hexagon grid

Tôi cần một số trợ giúp cho pla hình lục giác ce gắn với nhau trong một cấu trúc cố định. Tôi đã chơi xung quanh với các giá trị bố trí không thành công. TableView sẽ là một cách tiếp cận tốt hơn? Cảm ơn rất nhiều

+0

Chế độ xem 'HexView' từ đâu? – theomega

+0

Tôi chỉ nhầm lẫn tên của ứng dụng với bố cục GridView khi chỉnh sửa bài đăng đã được sửa. Cảm ơn. –

+0

Xem [this] (http: //www.gdreflections.com/2011/02/lục giác-grid-math.html) bài viết rất hay cũng có các mẫu Java đẹp. Bạn có thể thích ứng chúng với Android. – hypercode

Trả lời

5

Dưới đây là một số mã tôi đã sử dụng trong một ứng dụng (nó được gọi là 'Connect3, nếu bạn muốn chơi nó :)). Đây là một lớp bố cục tùy chỉnh vẽ hình lục giác trong một lưới. Lưới có thể là hình tam giác hoặc hình chữ nhật nghiêng.

Mã tính giới hạn (tính bằng pixel so với nguồn gốc của hình lục giác) của mỗi lần xem hình ảnh và sau đó gọi số imageView.layout(left,top,right,bottom) để đặt giới hạn được tính. Các tính toán không khó. Tham số chính là radius của hình lục giác. Từ đó, tổng chiều cao, tổng chiều rộng, chiều cao hiệu dụng và chiều rộng hiệu dụng (chiều cao/chiều rộng của lần xem ảnh tương ứng khoảng cách giữa các giới hạn trên cùng/bên trái của hai chế độ xem liên tiếp). Sau đó, nó đi xuống đến một số đơn giản cho các vòng để vẽ chúng.

Để làm cho số lượt xem có thể nhấp, chỉ cần đặt onClickListener khi bạn tạo chúng. (Tôi đã biến nó thành một thành viên trong lớp, bởi vì nó làm mọi thứ dễ dàng hơn).

Các chức năng onMeasure chỉ tính tổng chiều rộng và chiều cao của chế độ xem và gọi setMeasuredDimension với các giá trị đó.

Hình ảnh được sử dụng cho tất cả điều này chỉ là các hình lục giác đơn khi bạn nhìn thấy chúng ngay bên dưới thanh hành động. Lưu ý rằng hình ảnh là hình vuông.

@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 là dự án Github mà thực hiện một hình lục giác (hex) lưới.

Các vấn đề liên quan