71

I'm adding two buttons to the UI, but they appear on top of one another. I want them to appear next to each other. What am I missing in this code?

m_btnCrown = new ImageButton(this);
m_btnCrown.setImageResource(R.drawable.king_crown_thumb);
m_btnCrown.setAlpha(100);

RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
    RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);


addContentView(m_btnCrown, lp);


m_btnMonkey = new ImageButton(this);
m_btnMonkey.setImageResource(R.drawable.monkey_small);
m_btnMonkey.setAlpha(100);

lp = new RelativeLayout.LayoutParams(
    RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
lp.addRule(RelativeLayout.RIGHT_OF, m_btnCrown.getId());   

addContentView(m_btnMonkey, lp);
Onik
  • 19,396
  • 14
  • 68
  • 91
Karthik Murugan
  • 1,429
  • 3
  • 17
  • 28

3 Answers3

143

I have written a quick example to demonstrate how to create a layout programmatically.

public class CodeLayout extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Creating a new RelativeLayout
        RelativeLayout relativeLayout = new RelativeLayout(this);

        // Defining the RelativeLayout layout parameters.
        // In this case I want to fill its parent
        RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.FILL_PARENT,
                RelativeLayout.LayoutParams.FILL_PARENT);

        // Creating a new TextView
        TextView tv = new TextView(this);
        tv.setText("Test");

        // Defining the layout parameters of the TextView
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        lp.addRule(RelativeLayout.CENTER_IN_PARENT);

        // Setting the parameters on the TextView
        tv.setLayoutParams(lp);

        // Adding the TextView to the RelativeLayout as a child
        relativeLayout.addView(tv);

        // Setting the RelativeLayout as our content view
        setContentView(relativeLayout, rlp);
    }
}

In theory everything should be clear as it is commented. If you don't understand something just tell me.

Octavian Helm
  • 39,405
  • 19
  • 98
  • 102
  • 5
    Though this sample works, my actual problem (overlapping controls) remains unanswered. More searching revealed the solution in http://stackoverflow.com/questions/2305395/laying-out-views-in-relativelayout-programmatically/2499721#2499721 We should explicitly set id's using setId(). Only then RIGHT_OF rules make sense – Karthik Murugan Feb 13 '11 at 10:35
  • 1
    Well that is kind of self-explanatory. If you want to access something by its id you have to set it too. What I wanted to highlight with my answer was that you are doing it wrong. Calling `addContentView` will _override_ the content view which was set before or which is set with `setContentView`. – Octavian Helm Feb 13 '11 at 10:55
  • 3
    I don't think so. Just check this documentation: http://developer.android.com/reference/android/app/Dialog.html#addContentView(android.view.View, android.view.ViewGroup.LayoutParams) which says "Add an additional content view to the screen. Added after any existing ones in the screen -- existing views are NOT removed" – Karthik Murugan Feb 17 '11 at 07:42
  • this answer should be downvoted. It is hardly relevant to the OP's question and goes on a tangent – pcodex Sep 28 '19 at 08:34
  • I would recommend if you possibly can, to put the layout in XML and then use `LayoutInflater.inflate(...)` to create the actual objects. For example, if you needed to create a variable number of buttons, you could have a layout XML representing a single button, then inflate it multiple times in a loop. I have experienced many issues with trying to do **everything** programmatically, as some properties don't work in the same way as they do in XML – Adam Burley Jan 28 '21 at 13:17
22

Found the answer in How to lay out Views in RelativeLayout programmatically?

We should explicitly set id's using setId(). Only then, RIGHT_OF rules make sense.

Another mistake I did is, reusing the layoutparams object between the controls. We should create new object for each control

Community
  • 1
  • 1
Karthik Murugan
  • 1,429
  • 3
  • 17
  • 28
  • The layoutparams part was not wrong. It is totally valid the way you defined it but as you can read in my comment above it was not right how you added the views. – Octavian Helm Feb 13 '11 at 11:00
0
public class AndroidWalkthroughApp1 extends Activity implements View.OnClickListener {

    final int TOP_ID = 3;
    final int BOTTOM_ID = 4;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // create two layouts to hold buttons
        RelativeLayout top = new RelativeLayout(this);
        top.setId(TOP_ID);
        RelativeLayout bottom = new RelativeLayout(this);
        bottom.setId(BOTTOM_ID);

        // create buttons in a loop
        for (int i = 0; i < 2; i++) {
            Button button = new Button(this);
            button.setText("Button " + i);
            // R.id won't be generated for us, so we need to create one
            button.setId(i);

            // add our event handler (less memory than an anonymous inner class)
            button.setOnClickListener(this);

            // add generated button to view
            if (i == 0) {
                top.addView(button);
            }
            else {
                bottom.addView(button);
            }
        }

        RelativeLayout root = (RelativeLayout) findViewById(R.id.root_layout);

        // add generated layouts to root layout view
       // LinearLayout root = (LinearLayout)this.findViewById(R.id.root_layout);

        root.addView(top);
        root.addView(bottom);
    }

    @Override
    public void onClick(View v) {
        // show a message with the button's ID
        Toast toast = Toast.makeText(AndroidWalkthroughApp1.this, "You clicked button " + v.getId(), Toast.LENGTH_LONG);
        toast.show();

        // get the parent layout and remove the clicked button
        RelativeLayout parentLayout = (RelativeLayout)v.getParent();
        parentLayout.removeView(v);



    }
}
Durul Dalkanat
  • 7,266
  • 4
  • 35
  • 36