Dynamically adding a button to RelativeLayout not

2019-08-06 12:51发布

问题:

My goal is to add a number of buttons (in a 4 column grid) to a RelativeLayout depending on how many "items" are in the database. When I was first learning how to add buttons to a RelativeLayout I just created 6 static buttons and added them the following way (ItemButton is simple class that extends Button):

private void loadItemButtons2(){
    itemButtonLayout = (RelativeLayout)findViewById(R.id.itemButtonLayout);
    itemButtonLayout.removeAllViews();
    ArrayList<Item> items = db.getAllActiveItems();
    ItemButton b1, b2, b3, b4, b5, b6;
    b1 = new ItemButton(this, items.get(0));
    b2 = new ItemButton(this, items.get(1));
    b3 = new ItemButton(this, items.get(2));
    b4 = new ItemButton(this, items.get(3));
    b5 = new ItemButton(this, items.get(4));
    b6 = new ItemButton(this, items.get(5));

    RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams)b1.getLayoutParams();
    params1.addRule(RelativeLayout.ALIGN_PARENT_START);
    b1.setId(111);
    b1.setLayoutParams(params1);

    RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams)b2.getLayoutParams();
    params2.addRule(RelativeLayout.RIGHT_OF, 111);
    b2.setId(222);
    b2.setLayoutParams(params2);

    RelativeLayout.LayoutParams params3 = (RelativeLayout.LayoutParams)b3.getLayoutParams();
    params3.addRule(RelativeLayout.RIGHT_OF, 222);
    b3.setId(333);
    b3.setLayoutParams(params3);

    RelativeLayout.LayoutParams params4 = (RelativeLayout.LayoutParams)b4.getLayoutParams();
    params4.addRule(RelativeLayout.RIGHT_OF, 333);
    b4.setId(444);
    b4.setLayoutParams(params4);

    RelativeLayout.LayoutParams params5 = (RelativeLayout.LayoutParams)b5.getLayoutParams();
    params5.addRule(RelativeLayout.ALIGN_PARENT_START);
    params5.addRule(RelativeLayout.BELOW, 111);
    b5.setId(555);
    b5.setLayoutParams(params5);

    RelativeLayout.LayoutParams params6 = (RelativeLayout.LayoutParams)b6.getLayoutParams();
    params6.addRule(RelativeLayout.RIGHT_OF, 555);
    params6.addRule(RelativeLayout.BELOW, 222);
    b6.setId(666);
    b6.setLayoutParams(params6);

    itemButtonLayout.addView(b1);
    itemButtonLayout.addView(b2);
    itemButtonLayout.addView(b3);
    itemButtonLayout.addView(b4);
    itemButtonLayout.addView(b5);
    itemButtonLayout.addView(b6);
}

And this gives me a perfect result:

But this is the dynamic solution I came up with, and to me it looks like it is doing the exact same thing but the results come out super wonky:

private void loadItemButtons(){
    itemButtonLayout = (RelativeLayout)findViewById(R.id.itemButtonLayout);
    itemButtonLayout.removeAllViews();
    ArrayList<Item> items = db.getAllActiveItems();
    int colCount = 0;
    int rowCount = 0;
    int i = 0;

    while(i < items.size()-1){
        ItemButton newItemButton = new ItemButton(this, items.get(i));
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)newItemButton.getLayoutParams();
        newItemButton.setId(i);

        if(colCount == 0){
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
        }else if(colCount == 1){
            layoutParams.addRule(RelativeLayout.RIGHT_OF, i-1);
        }else if(colCount == 2){
            layoutParams.addRule(RelativeLayout.RIGHT_OF, i-1);
        }else if(colCount == 3){
            layoutParams.addRule(RelativeLayout.RIGHT_OF, i-1);
        }

        //If we are in any row except the top row, place in reference to the button above it
        if(rowCount != 0){
            layoutParams.addRule(RelativeLayout.BELOW, i-4);
        }

        newItemButton.setLayoutParams(layoutParams);
        itemButtonLayout.addView(newItemButton);

        if(colCount == 3){
            colCount = 0;
            rowCount += 1;
        }else{
            colCount += 1;
        }

        i++;
    }
}

Is anyone able to see what I am doing incorrectly or different from the first example??? Any advice is much appreciated!

回答1:

The reason this is failing for you is because of the IDs you are using. Android uses "reserved" ids for things like the general content area of the app.

Using your code, I was able to add 1000 to each ID and generate the intended result.

Do note my cleanup below:

private void loadItemButtons(){
    itemButtonLayout = (RelativeLayout)findViewById(R.id.itemButtonLayout);
    itemButtonLayout.removeAllViews();
    List<String> items = itemList;
    int colCount = 0;
    int rowCount = 0;

    // # of items per column
    int colSpan = 4;

    final int itemListSize = itemList.size();
    for (int i = 0; i < itemListSize; i++) {
        int id = 1000 + i;
        ItemButton newItemButton = new ItemButton(this, items.get(i));
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        newItemButton.setId(id);

        if(colCount == 0)
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
        else
            layoutParams.addRule(RelativeLayout.RIGHT_OF, id-1);


        //If we are in any row except the top row, place in reference to the button above it
        if(rowCount != 0)
            layoutParams.addRule(RelativeLayout.BELOW, id-colSpan);

        newItemButton.setLayoutParams(layoutParams);
        itemButtonLayout.addView(newItemButton);

        if(colCount == colSpan - 1)
            rowCount += 1;

        colCount = (colCount + 1) % colSpan;
    }
}

Also, as mentioned in my comment on the original post, you really should use a gridview for this, it's what it was built for.

I can dig a hole with a pitchfork, but I bet a shovel would work better.



回答2:

I didn't test the code:

private void loadItemButtons(){
    itemButtonLayout = (RelativeLayout)findViewById(R.id.itemButtonLayout);
    itemButtonLayout.removeAllViews();
    ArrayList<Item> items = db.getAllActiveItems();
    int colCount = 0;
    int rowCount = 0;
    int i = 0;

    while(i < items.size())
   {
        ItemButton newItemButton = new ItemButton(this, items.get(i));
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)newItemButton.getLayoutParams();
        newItemButton.setId(i);

        if(colCount == 0)
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
        else 
            layoutParams.addRule(RelativeLayout.RIGHT_OF, i-1);


        //If we are in any row except the top row, place in reference to the button above it
        if(rowCount != 0){
            layoutParams.addRule(RelativeLayout.BELOW, i-4);
        }

        itemButtonLayout.addView(newItemButton, i, layoutParams);

        if(colCount == 3){
            colCount = 0;
            rowCount += 1;
        }else{
            colCount += 1;
        }

        i++;
    }
}