简体   繁体   中英

How do I fill a grid with ImageButtons programmatically?

I'm new to Android development so I've been working on a chess app in order to teach myself. However, I am now stuck. Essentially, I need a good way to draw an 8x8 grid of ImageButtons such that:

  1. The buttons fill the entire grid
  2. Grid space is evenly distributed among the buttons
  3. There are no gaps between buttons (clarifying #2)
  4. The grid is square shaped and its size can be controlled (I'd like to be able to automatically resize based on screen size).

Or, put simply, it should look like a standard chess board :)

I've tried several layouts with no success. Currently, this is the best I've been able to do:

“棋盘”

I'm using a GridLayout in the following way inside of PlayGameActivity (Where the board should be drawn):

public void onStart(){
    super.onStart();

    board = (GridLayout)findViewById(R.id.chessboard);
    board.setColumnCount(8);
    board.setRowCount(8);

    for(int i = 0; i < 8; i++){
        for(int j = 0; j < 8; j++){
            ImageButton square = squares[i][j] = new ImageButton(this);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            params.rightMargin = 0;
            params.topMargin = 0;
            params.height = params.WRAP_CONTENT;
            params.width = params.WRAP_CONTENT;
            params.setGravity(Gravity.FILL);
            params.rowSpec = GridLayout.spec(i);
            params.columnSpec = GridLayout.spec(j);

            board.addView(square, params);

            //board.addView(square);
        }
    }}

And the chessboard is defined via XML like this:

<GridLayout
    android:id="@+id/chessboard"
    android:layout_width="353dp"
    android:layout_height="353dp"
    android:layout_marginBottom="104dp"
    android:layout_marginEnd="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="104dp"
    android:background="#000000"
    android:gravity="center_horizontal"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:layout_constraintBottom_creator="1"
    tools:layout_constraintLeft_creator="1"
    tools:layout_constraintRight_creator="1"
    tools:layout_constraintTop_creator="1">
</GridLayout>

All solutions I've found for this type of problem have been in the form of Android XML. Maybe my concerns about such an approach are based on ignorance, but my understanding is that I'd have to copy and paste 64 squares into a GridLayout or something. Also, I'm not sure how I'd resize based on screen size with that approach. Ideally, I'm looking for a strictly programmatic solution (and this is my preferred method of UI design anyway).

My suggestion would be to modularize with xml by using include ( link ):

<include layout="@layout/titlebar"/>

Using include allows you to write a piece of XML code once in its own file, and then use it multiple times. I would also suggest against using GridLayout in most cases because they just don't give you as much control as some of the other layout types. If this were my code, this is what I would do:

  1. Create an ImageButton "square" in its own XML file with android:layout_weight="1" .
  2. Create a LinearLayout "row" in its own XML file with android:orientation="horizontal" , android:layout_weight="1" , and android:weightSum="8" , then copy and paste 8 include s with layout="@layout/[your_image_button]" .
  3. Create an outer LinearLayout where you currently have your GridLayout . This one would have android:orientation="vertical" and android:weightSum="8" . Then copy and paste 8 include s with layout="@layout/[your_linear_layout_row]" .

There are many ways to do this, but this way gives you a lot of control on how everything is laid out spatially, and the logic of it is very similar to the 'array of arrays' approach you're currently using to dynamically lay everything out. If you want to go the dynamic java route, my suggestion would be to do this LinearLayout-based grid approach in java (you can even create the ImageButton in XML and use a LayoutInflater to inflate copies of the ImageButton). In the outer for loop, you can create a new LinearLayout and add it to the outer LinearLayout; then in the inner for loop, create the ImageButton and add it to the inner LinearLayout.

Edit : Good point about the rows being different! That makes the pure XML solution less clean. If you go with pure XML, I would just do step 2 above twice: one time with white then black; the other time with black then white. For a black tile, this might look like:

<include layout="@layout/your_imagebutton"
  android:backgroundColor="#000"
/>

If this approach is too cumbersome for you, you could set the colors dynamically by looping through the LinearLayout rows and ImageButton tiles to set the background color. I think you'd find it easier than it was in your GridLayout approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM