2014-04-15 3 views
7

Ein Biene Layout wie diesesMöglich, ein Bienenstock-XML-Layout in Android zu machen?

Die farbige Nesselsucht ist nur so zu verstehen, wie ich Elemente festzulegen aussehen sollte.

Welche Layout Widget schlagen Sie vor?

Ich habe versucht mit GridView, aber ich kann solche Zellen nicht machen, dann FrameLayout, aber nicht mit Pixel (oder dp) Werte beim Einstellen der Stock Speicherort beschäftigen.

Ich bin bei meinem Verstand Ende. Ich bin der Schlussfolgerung nahe, dass so etwas in Android nicht auf qualitativ hochwertige Weise und ohne Verwendung von Spiel-ähnlichen Bibliotheken möglich ist. Ich hoffe, jemand gibt mir einen guten Hinweis zur Lösung.

+1

Sie haben meine Neugier geweckt und ich habe gegoogelt und mich gefragt, ob das möglich ist. Alles deutet darauf hin, dass es nicht (das heißt, nicht mit einfachen Mitteln) ist, und nicht-rechteckige Layouts werden nur durch "Betrug" erreicht, wie http://StackOverflow.com/a/13879492/168719 oder http://stackoverflow.com/a/19583072/168719 - Mit anderen Worten, sie werden nur als nicht-rechteckig dargestellt und das Klicken im transparenten Bereich wird ignoriert, um diese Impression zu erhalten. In Ihrem Fall müsste es jedoch an die angrenzende Kachel delegiert werden, und die Handhabung würde den Code noch komplizierter machen. –

+0

Könnten Sie vielleicht "schummeln", indem Sie eine 'Ansicht' ableiten, den Bienenstock mit einem hexagonalen' Pfad' herausziehen, indem Sie die offset() 'Methode durch die Zeilen iterieren, jeweils mit einem _sightly_ anderen RGB-Wert füllen und dann prüfen dieser Wert aus den Koordinaten in 'onTouchEvent()'? (Ich denke auch, dass es eher eine Wabenform ist, die irgendwie angemessen ist.) –

+1

Ich denke du könntest auch feststellen, in welchem ​​Bereich sich die Berührung befindet, durch einfaches Zahlenknacken, aber das ist mehr Mathematik, als ich tun möchte. __Bearbeiten: __ Jemand hat schon Mathe gemacht, und in Java! http://www.gdreflections.com/2011/02/hexagonal-grid-math.html –

Antwort

6

Da ich mir über den beabsichtigten Zweck oder die Anforderungen nicht sicher bin, handelt es sich lediglich um einen Proof-of-Concept. Die Klasse HoneycombView hat keine illegalen Argumentprüfungen oder Ausnahmen jeglicher Art. Die meisten Eigenschaften sind "fest codiert", wie z. B. Wandfarbe und -breite, Zellenfarben und -ausrichtung usw. Diese können alle leicht durch Hinzufügen der geeigneten Einstellvorrichtungen und Getter modifiziert werden. Ich habe eine einfache Activity Klasse enthalten, um seine Verwendung zu demonstrieren.

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

Und die 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

ich mit meinem ersten Vorschlag ging leicht ein Gebiet Farbe zu verändern, wo Ereignisse Berührung zu bestimmen auftreten würden, aber ich endete tun, so in ein Mitglied Bitmap, so dass die Farben auf dem Bildschirm nicht betroffen sind. Wie Sie aus dem Code entnehmen können, sind die Zellen in diesem Bitmap so gefüllt, dass sie relevante Zellinformationen in den RGB-Komponenten kodieren. Die rote Komponente wird auf 1 gesetzt, um anzuzeigen, dass ein gegebenes Pixel innerhalb der relevanten Region liegt (d. H. Innerhalb der gesamten "Wabe"). Die Spalten- und Zeilenpositionen der Zelle innerhalb des Gitters werden dann in den Komponenten Grün und Blau codiert und können einfach in der onTouchEvent()-Methode abgerufen werden.

Die Methode initialize() legt die Anzahl der Spalten und Zeilen im Raster fest, und im Beispiel Activity sind sie so eingestellt, dass sie eine Querformatausrichtung bevorzugen. Nur zur Klarheit, in meiner Implementierung, mit den Zellen so ausgerichtet, dass die lange Achse horizontal ist, definiere ich eine Reihe, die aus den Zellen besteht, deren Achsen kolinear sind. Der Link, den ich in meinem Kommentar gepostet habe, hat die Dinge anders gemacht.

Ich habe fast vergessen, Kredit zu geben: Ich habe die sechseckige Path Code von this question.

+0

Ist es scrollbar? –

+0

Nicht so wie es ist, aber ich könnte mir vorstellen, dass man es ohne großen Aufwand in eine 'ScrollView' verpacken könnte. Das habe ich allerdings noch nicht getestet. –

+0

Okay. Ich werde es versuchen. Danke übrigens –

Verwandte Themen