2014-04-15 20 views
7

Một bố trí tổ ong sẽ trông như thế nàyCó thể tạo bố cục XML tổ ong trong Android?

Các tổ ong màu là chỉ để bạn hiểu làm thế nào tôi phải nằm xuống yếu tố.

Bạn có đề xuất sử dụng tiện ích con nào của Layout?

Tôi đã thử với GridView nhưng tôi không thể tạo các ô như vậy, sau đó FrameLayout nhưng không muốn xử lý các giá trị pixel (hoặc dp) khi đặt vị trí hive.

Tôi sắp hết trí thông minh. Tôi gần kết luận rằng một cái gì đó như thế này không thể được thực hiện trong Android một cách chất lượng cao và không sử dụng thư viện giống như trò chơi. Tôi hy vọng một người nào đó sẽ cho tôi một đầu mối tốt cho giải pháp.

+1

Bạn thực sự làm dấy lên sự tò mò của tôi và tôi đã làm một số googling, tự hỏi liệu nó có thể. Tất cả mọi thứ chỉ ra rằng không, nó không phải là (có nghĩa là, không phải bằng phương tiện đơn giản), và bố trí không hình chữ nhật chỉ đạt được bằng cách "gian lận", như http://stackoverflow.com/a/13879492/168719 hoặc http://stackoverflow.com/a/19583072/168719 - nói cách khác, chúng chỉ được thực hiện để xuất hiện không phải hình chữ nhật và nhấp vào trong khu vực trong suốt chỉ bị bỏ qua để duy trì hiển thị đó. Trong trường hợp của bạn mặc dù nó sẽ phải được giao cho gạch liền kề, và phải xử lý này sẽ làm phức tạp thêm mã. –

+0

Bạn có thể "lừa dối" bằng cách phân lớp 'Chế độ xem', vẽ tổ ong bằng một' Đường dẫn' lục giác, sử dụng phương thức 'offset()' lặp qua các hàng, điền chúng với giá trị RGB khác nhau _slightly_, sau đó kiểm tra giá trị đó từ các coords trong 'onTouchEvent()'? (Ngoài ra, tôi nghĩ đó là một hình dạng tổ ong hơn, thích hợp hơn). –

+1

Tôi đoán bạn cũng có thể xác định vùng nào chạm vào thông qua việc crunching số đơn giản, nhưng đó là toán học nhiều hơn tôi muốn làm. __Edit: __ Ai đó đã làm toán và trong Java! http://www.gdreflections.com/2011/02/hexagonal-grid-math.html –

Trả lời

6

Vì tôi không chắc chắn về mục đích hoặc yêu cầu dự định, sau đây chỉ đơn thuần là bằng chứng-khái niệm. Lớp học HoneycombView không có kiểm tra đối số bất hợp pháp hoặc thực sự xử lý ngoại lệ. Hầu hết các thuộc tính được "cứng mã hóa", chẳng hạn như màu tường và chiều rộng, màu sắc và hướng của ô, vv Tất cả đều dễ dàng sửa đổi với việc bổ sung các bộ định vị và getters thích hợp. Tôi đã bao gồm một lớp đơn giản Activity để chứng minh việc sử dụng nó.

public class HoneycombView extends View 
{ 
    private Paint wallPaint = new Paint(); 
    private Paint fillPaint = new Paint(); 
    private Paint cachePaint = new Paint(); 
    private Path combPath; 
    private Bitmap cacheBmp; 
    private Canvas cacheCan; 

    private int cellWidth; 
    private int columns; 
    private int rows; 
    private boolean[][] cellSet; 

    private OnCellClickListener listener; 

    public HoneycombView(Context context) 
    { 
     this(context, null); 
    } 

    public HoneycombView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 

     wallPaint.setColor(Color.YELLOW); 
     wallPaint.setStyle(Paint.Style.STROKE); 
     wallPaint.setStrokeWidth(5f); 

     fillPaint.setStyle(Paint.Style.FILL);  
     cachePaint.setStyle(Paint.Style.FILL); 
    } 

    public void initialize(int columns, int rows) 
    { 
     this.columns = columns; 
     this.rows = rows; 

     this.cellSet = new boolean[columns][rows]; 
    } 

    public interface OnCellClickListener 
    { 
     public void onCellClick(int column, int row); 
    } 

    public void setOnCellClickListener(OnCellClickListener listener) 
    { 
     this.listener = listener; 
    } 

    public void setCell(int column, int row, boolean isSet) 
    { 
     cellSet[column][row] = isSet; 
     invalidate(); 
    } 

    public boolean isCellSet(int column, int row) 
    { 
     return cellSet[column][row]; 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) 
    { 
     super.onSizeChanged(w, h, oldw, oldh); 

     cacheBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     cacheCan = new Canvas(cacheBmp); 

     cellWidth = 2 * w/(2 * columns + columns - 1); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     super.onDraw(canvas); 

     canvas.drawColor(Color.WHITE); 

     boolean oddRow; 
     int xOff; 

     combPath = getHexPath(cellWidth/2f, cellWidth/2f, (float) (cellWidth * Math.sqrt(3)/4)); 

     for (int r = 0; r < rows; r++) 
     { 
      oddRow = (r & 1) == 1; 
      xOff = 0; 

      for (int c = 0; c < columns; c++) 
      { 
       if (!(oddRow && c == columns - 1)) 
       { 
        fillPaint.setColor(cellSet[c][r] ? Color.RED : Color.WHITE); 
        canvas.drawPath(combPath, fillPaint); 

        canvas.drawPath(combPath, wallPaint); 

        cachePaint.setColor(Color.argb(255, 1, c, r)); 
        cacheCan.drawPath(combPath, cachePaint); 

        combPath.offset((int) (1.5f * cellWidth), 0); 
        xOff += 1.5f * cellWidth; 
       } 
      } 

      combPath.offset(-xOff + (oddRow ? -1 : 1) * 3 * cellWidth/4, (float) (cellWidth * Math.sqrt(3)/4)); 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) 
    { 
     if (event.getAction() != MotionEvent.ACTION_DOWN) 
      return true; 

     int pixel = cacheBmp.getPixel((int) event.getX(), (int) event.getY()); 

     int r = Color.red(pixel); 
     if (r == 1) 
     { 
      int g = Color.green(pixel); 
      int b = Color.blue(pixel); 

      if (listener != null) 
      { 
       listener.onCellClick(g, b); 
      } 
     } 
     return true; 
    } 

    private Path getHexPath(float size, float centerX, float centerY) 
    { 
     Path path = new Path(); 

     for (int j = 0; j <= 6; j++) 
     { 
      double angle = j * Math.PI/3; 
      float x = (float) (centerX + size * Math.cos(angle)); 
      float y = (float) (centerY + size * Math.sin(angle)); 
      if (j == 0) 
      { 
       path.moveTo(x, y); 
      } 
      else 
      { 
       path.lineTo(x, y); 
      } 
     } 

     return path; 
    } 
} 

Activity:

public class MainActivity extends Activity 
implements HoneycombView.OnCellClickListener 
{ 
    HoneycombView honey; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     getWindow().requestFeature(Window.FEATURE_NO_TITLE); 

     honey = new HoneycombView(this); 
     honey.initialize(4, 8); 
     honey.setOnCellClickListener(this); 

     setContentView(honey); 
    } 

    @Override 
    public void onCellClick(int column, int row) 
    { 
     honey.setCell(column, row, !honey.isCellSet(column, row)); 
    } 
} 

Sample image

tôi đã đi với đề nghị ban đầu của tôi về hơi thay đổi màu sắc của một khu vực để xác định nơi các sự kiện liên lạc có thể xảy ra, nhưng tôi đã kết thúc làm như vậy trong một thành viên Bitmap để các màu trên màn hình không bị ảnh hưởng. Như bạn có thể thấy từ mã, các ô trong số Bitmap này được điền theo cách để mã hóa thông tin ô có liên quan trong các thành phần RGB của Color. Thành phần màu đỏ được đặt thành 1 để cho biết rằng một pixel nhất định nằm trong vùng thích hợp (nghĩa là trong toàn bộ "tổ ong"). Các vị trí cột và hàng của ô trong lưới điện sau đó được mã hóa trong các thành phần Xanh lục và Xanh dương, và dễ dàng được truy xuất theo phương thức onTouchEvent().

Phương pháp initialize() đặt số cột và hàng trong lưới và trong mẫu Activity chúng được đặt để ưu tiên định hướng ngang. Chỉ cần cho rõ ràng, trong thực hiện của tôi, với các tế bào theo định hướng để trục dài là ngang, tôi xác định một hàng để bao gồm các tế bào có trục là tuyến tính. Liên kết tôi đã đăng trong nhận xét của tôi đã làm mọi thứ khác đi.

Tôi gần như quên cung cấp tín dụng: Tôi nhận mã lục giác Path lục giác từ this question.

+0

Có thể cuộn được không? –

+0

Không phải là nó, nhưng tôi tưởng tượng bạn có thể quấn nó trong một 'ScrollView' mà không có quá nhiều rắc rối. Tôi đã không thử nghiệm điều đó, mặc dù. –

+0

OK. Tôi sẽ thử. Cảm ơn btw –

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