In the code snippet below there's one commented line. When I uncomment that line, then the contents of LinearLayout are not displayed in a TableRow. Without setting the LayoutParams, the row displays both texts. I don't understand this behavior. I know that I can include complex views via xml files, but I'd rather understand what's wrong with this code:
TableLayout tableLayout = (TableLayout) findViewById(R.id.table);
TableRow tableRow = new TableRow(this );
tableRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
// when I comment out this line, the row only shows the second text.
// linearLayout.setLayoutParams(layoutParams);
TextView textLabel = new TextView(this);
textLabel.setText("inside linear layout");
linearLayout.addView(textLabel);
TextView message = new TextView(this);
message.setText( "inside tablerow");
tableRow.addView(linearLayout);
tableRow.addView(message);
tableLayout.addView(tableRow);
Assuming the question is something like "What's the issue of this? How to resolve this?", here's my answer:
When you are setting LayoutParams to a View, those params would be used by the parent of this View to layout that View appropriately. So in your case what you have done is following:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(...);
linearLayout.setLayoutParams(layoutParams);
tableRow.addView(linearLayout);
Now, the tableRow is confused, because it expects TableRow.LayoutParams in order to layout the view appropriately, but it suddenly finds out some other layout params. Whereas, had you not explicitly specified params (i.e. when linearLayout.setLayoutParams() is commented out), the default layout params would be generated.
#Override
protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(); // this is TableRow.LayoutParams
}
So, instead of creating LinearLayout.LayoutParams, create TableRow.LayoutParams:
TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(...);
linearLayout.setLayoutParams(layoutParams);
tableRow.addView(linearLayout);
Related
I have created a fragment which should display table of buttons. I used table layout to create a table. But the button table doesn't display in the fragment. What is the problem related to this code and how can I overcome this???
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
ArrayList buttons = new ArrayList();
ScrollView sv = new ScrollView(this.getActivity());
//Set a TableLayout to add buttons
TableLayout tl= new TableLayout(getActivity());
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
tl.setLayoutParams(params);
tl.setOrientation(TableLayout.HORIZONTAL);
for(int i=0;i<5;i++){
TableRow row=new TableRow(this.getActivity());
LayoutParams paramrow = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
row.setLayoutParams(paramrow);
for(int j=0;j<2;j++){
Button button = new Button(getActivity());
button.setText("testing");
button.setPadding(5, 5, 5, 5);
LayoutParams parab = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(parab);
row.addView(button);
buttons.add(button);
}
tl.addView(row);
}
sv.addView(tl);
}
You're using the wrong type of LayoutParams in at least two places. Views need to use the type of LayoutParams that correspond to their container. Therefore Views contained directly in a TableLayout - i.e., the TableRows - should use TableLayout.LayoutParams. The Views contained in TableRows - the Buttons, in this case - should use TableRow.LayoutParams. And finally, the TableLayout is in a ScrollView, so it should use ScrollView.LayoutParams, which is actually FrameLayout.LayoutParams, since ScrollView extends FrameLayout.
It also appears that you're not adding the ScrollView to the Fragment's View anywhere. I would mention, too, that it might be preferable to define the ScrollView and the TableLayout in layout xml, inflate this layout in onCreateView(), and dynamically create only what needs to be - i.e., the TableRows and Buttons.
For creating a structure like the image in android, I tried the following code.
But showing this error. Please help
My code looks like
public void setValues(){
LinearLayout table=(LinearLayout)findViewById(R.id.mainWrap);
LinearLayout row=new LinearLayout(this);;
for(int i=0;i<5;i++){
if(i%2==0){
row= new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
row.setLayoutParams(lp);
}
FrameLayout layout = new FrameLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams((width/2)-10,(height/2)-10);
params.setMargins(5, 5, 5, 5);
layout.setLayoutParams(params);
if(i%2==0){
layout.setBackgroundColor(Color.parseColor("#CACACA"));
}
else {
layout.setBackgroundColor(Color.parseColor("#333333"));
}
ProgressBar pr=new ProgressBar(this);
FrameLayout.LayoutParams params_p = new FrameLayout.LayoutParams((width/6),(width/6));
params_p.gravity=Gravity.CENTER;
pr.setLayoutParams(params_p);
layout.addView(pr);
ImageView im=new ImageView(this);
FrameLayout.LayoutParams params_im = new FrameLayout.LayoutParams((width/2),(width/2));
im.setImageResource(R.drawable.man);
im.setLayoutParams(params_im);
layout.addView(im);
row.addView(layout);
table.addView(row);
}
Error is
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
Thanks in advance
I have a feeling the problem is here:
LinearLayout row=new LinearLayout(this);;
for(int i=0;i<5;i++){
The first time it loops row will be replaced by your second assignment of it and held in the variable OUTSIDE of the loop, the second time it is not replaced and because it is outside of the loop, it is the same row you're trying to add to the table again. Just swap the order of the lines above.
I have done some research, but the answer i found does not work for me. Here is some part of my code. the R.id.relative is the id of the relativelayout in the xml file
RelativeLayout RL = (RelativeLayout) findViewById(R.id.relative);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
TextView title = new TextView(this);
title.setText(" History ");
title.setId(99099);
title.setTextSize(30);
title.setGravity(Gravity.CENTER);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
title.setLayoutParams(params);
RL.addView(title);
RelativeLayout.LayoutParams test_params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
Button test = new Button(this);
test.setText(" Back ");
test_params.addRule(RelativeLayout.BELOW,99099);
test.setId(199291);
test.setGravity(Gravity.CENTER);
test.setLayoutParams(test_params);
RL.addView(test);
RelativeLayout.LayoutParams test_params2 = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
Button test2 = new Button(this);
test2.setText(" Clear ");
test_params2.addRule(RelativeLayout.BELOW,test.getId());
test2.setGravity(Gravity.CENTER);
test.setLayoutParams(test_params2);
RL.addView(test2);
all 3 items did show up, but they stack together. I can't get them below another.
Could anyone help ?
From what I've been able to find out, you have to add the view using LayoutParams. Here's an example:
LinearLayout linearLayout = new LinearLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
parentView.addView(linearLayout, relativeParams);
And to relatively position your items programmatically you have to assign ids to them, this stops them from 'overlapping'.
TextView tv1 = new TextView(this);
tv1.setId(1);
TextView tv2 = new TextView(this);
tv2.setId(2);
Then addRule(RelativeLayout.RIGHT_OF, tv1.getId());
Change test.setLayoutParams(test_params2); to test2.setLayoutParams(test_params2);
Explanation: You have inadvertently set the layout params of test a second time, with params that instruct it to be below itself, which I guess just puts it top-left (default placement in a RelativeLayout). Since you never give test2 any layout params, it also gets default placement. So everything is at the top and thus appear atop each other.
Incidentally, if you just want them arranged linearly, why not use a vertical LinearLayout?
The rule you have added is causing your view to be stacked together.If you need to add it should be used by the following rule.
test_params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 1);
Next, add the view to your RelativeLayout with your LayoutParams:
RL.addView(yourAdView, rLParams);
same goes for the each cases.try to run.It will solve your problem
I created a custom view. In it, theres a line, a textview, another line. beneath the bottom line, i wanted to put a new horizontally oriented linearlayout. when i run it, this nested linearlayout doesnt seem to show up at all. Instead, i can see the test button right underneath the bottom line. what am i doing wrong?
public class MyView extends LinearLayout {
public MyView(Context context, Question question) {
super(context);
// this.setLayoutParams(params);
this.setOrientation(VERTICAL);
this.setBackgroundColor(Color.WHITE);
LinearLayout.LayoutParams lineParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 2);
View topLine = new View(context);
lineParams.setMargins(0, 15, 0, 0);
topLine.setBackgroundColor(Color.argb(255, 0, 159, 218));
topLine.setLayoutParams(lineParams);
this.addView(topLine);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
//Challenge Question
TextView questionText = new TextView(context);
questionText.setTextColor(Color.BLACK);
questionText.setTextSize(14);
questionText.setLayoutParams(params);
questionText.setGravity(Gravity.CENTER_HORIZONTAL);
questionText.setText(question.getQuestion());
this.addView(questionText);
View bottomLine = new View(context);
bottomLine.setBackgroundColor(Color.argb(255, 0, 159, 218));
bottomLine.setLayoutParams(lineParams);
this.addView(bottomLine);
LinearLayout innerLayout = new LinearLayout(context);
LinearLayout.LayoutParams innerLayoutParams = new LinearLayout.LayoutParams(300, LayoutParams.WRAP_CONTENT);
innerLayout.setLayoutParams(innerLayoutParams);
innerLayout.setBackgroundColor(Color.RED);
innerLayout.setOrientation(HORIZONTAL);
//TableLayout for the multiple choices
TableLayout tableLayout = new TableLayout(context);
LayoutParams tableLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// tableLayoutParams.weight = .8f;
tableLayout.setBackgroundColor(Color.RED);
tableLayout.setLayoutParams(tableLayoutParams);
innerLayout.addView(tableLayout);
this.addView(innerLayout);
Button button = new Button(context);
button.setLayoutParams(params);
button.setText("testing 123");
this.addView(button);
}
Note that I pasted the code without all the stuff that I added to the tablelayout. I probably should have pasted that too. But it didn't work when I did that either. but either way, if i set the nested linearlayout to 300 width and set a background color of red to it, i should at least see it, no?
Think about what the height of the inner layout should be. Right now it is wrap_content and contains a TableLayout (with no rows) with its height also set to wrap_content. There doesn't seem to be anything in that inner layout giving it a height dimension, so that may be why it is not being displayed.
Trying the following will make your layout visible:
LinearLayout.LayoutParams innerLayoutParams = new LinearLayout.LayoutParams(300, 300);
More usefully, you can try adding something with a real width/height to the TableLayout.
Also consider writing your layout in XML to better separate your application logic and the presentation.
I'm trying to create a TableLayout programatically. It just won't work. The same layout in an xml file works though. This is what I have:
public class MyTable extends TableLayout
{
public MyTable(Context context) {
super(context);
setLayoutParams(new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
TableRow row = new TableRow(context);
row.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
Button b = new Button(getContext());
b.setText("hello");
b.setLayoutParams(new LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
row.addView(b);
addView(row)
}
}
...
// In main activity:
MyTable table = new MyTable(this);
mainLayout.addView(table);
When I run this, I don't get a crash, but nothing appears. If I get rid of the TableRow instance, at least the button does appear as a direct child of the TableLayout. What am I doing wrong?
Just to make the answer more clear:
TableLayout.LayoutParams tableParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT);
TableRow.LayoutParams rowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
TableLayout tableLayout = new TableLayout(context);
tableLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));// assuming the parent view is a LinearLayout
TableRow tableRow = new TableRow(context);
tableRow.setLayoutParams(tableParams);// TableLayout is the parent view
TextView textView = new TextView(context);
textView.setLayoutParams(rowParams);// TableRow is the parent view
tableRow.addView(textView);
Explanation
When you call setLayoutParams, you are supposed to pass the LayoutParams of the parent view
It turns out I needed to specify TableRowLayout, TableLayout etc for the layout params, otherwise the table just won't show!
For me, to get mine I had to call addContentView().
A good solution is to inflate layout files for each instance of row you want to create. See this post : How to duplicate Views to populate lists and tables?
Your problem is at this line:
b.setLayoutParams(new LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
You need to change LayoutParams to TableRow.LayoutParams:
b.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT));