I need to add TextViews to a Layout (RelativeLayout or LinearLayout I don't care) programatically.
I want something like this:
After the textview 4 there is no more space on the right side so the next TextView will be placed in a new Line bellow.
This is what I have done:
Create a LinearLayout in the xml file:
<LinearLayout
android:id="#+id/my_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
In my code, I loop over a list of Objects and add a new TextView for each objekt:
LinearLayout myLinearLayout = (LinearLayout) itemView.findViewById(R.id.my_linear_layout);
for(MyObject object : myObjectList) {
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(20, 0, 20, 0); // llp.setMargins(left, top, right, bottom);
final TextView textView = new TextView(context);
textView.setText(object.getName());
textView.setLayoutParams(params);
myLinearLayout.addView(textView, params);
}
But this is the result I get:
I have thought adding LinearLayouts vertically instead of TextViews, but still my problem is that I don't know when I need to add the next the next one, I mean, when there is no more space on the right side.
I have also tried it with TableLayout but still the same problem, I don't know when I have to add the next row.
Any ideas? Maybe there is a View that already solves that problem and I don't know...
Related
i know, there are a lot of questions like this. I read a lot on stackoverflow and google about this topic, but nothing help me :(
Ok, here is the problem. I have a small app. In this app i have a fragment. The layout.xml for this fragment includes a placeholder linearlayout like the following
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/placeholderLinLayout">
</LinearLayout>
The fragment has a button. If u click on it a DialogFragmentPopup opens and u can enter some data-stuff. After you enter the data you can click on another button on this dialog and the data will be transfere to the main-fragment. Here i call a method which should generate programmatically a layout to present the data. I use the following code
myRoot = (LinearLayout) view.findViewById(R.id.placeholderLinLayout);
innerLayout = new LinearLayout(view.getContext());
innerLayout.setOrientation(LinearLayout.VERTICAL);
innerLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
LinearLayout productHeaderLayout = new LinearLayout(getContext());
productHeaderLayout.setOrientation(LinearLayout.HORIZONTAL);
productHeaderLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
TextView product_header = new TextView(getContext());
product_header.setText("Produkt");
product_header.setLayoutParams(layoutParams);
TextView amount_header = new TextView(getContext());
amount_header.setText("Menge");
amount_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
amount_header.setLayoutParams(layoutParams);
TextView packaging_header = new TextView(getContext());
packaging_header.setText("Verpackung");
packaging_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
packaging_header.setLayoutParams(layoutParams);
TextView price_header = new TextView(getContext());
price_header.setText("Preis");
price_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
price_header.setLayoutParams(layoutParams);
TextView payment_header = new TextView(getContext());
payment_header.setText("Zahlart");
payment_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
payment_header.setLayoutParams(layoutParams);
productHeaderLayout.addView(product_header);
productHeaderLayout.addView(amount_header);
productHeaderLayout.addView(packaging_header);
productHeaderLayout.addView(price_header);
productHeaderLayout.addView(payment_header);
innerLayout.addView(productHeaderLayout);
The problem is, that the first textview push all other textviews out of the visible space, see the screenshot
What i want to do is, that these 5 textviews spread out automatically to the existing width. I googled a lot and the code i post here is the result of which i found many times on the internet.
So i hope someone can help find out the problem in my code :)
Greetings
Set all your TextView layout paramters to this:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f);
And remove .setWidth(ViewGroup.LayoutParams.MATCH_PARENT); from all the TextViews.
This will guarantee that all the views will have same weight set to them, and that weight gives all the views in LinearLayout same Width (or Height if orientation is set to vertical).
The issue is that your setting the TextView to MATCH_PARENT in its width. So one TextView takes the whole screen and the other starts just out of it. To solve this set the layoutparam width to WRAP_CONTENT.
Better yet, if you want to spread it, you can use the LinearLayout's weight property so they take as much space as they can:
textview.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
The third parameter 1f is the weight. A weight of one means it'll take all the available space without intruding on the other children, hence they will all spread evenly.
If you want to have your TextViews side by side, you must set the orientation of the LinearLayout to horizontal instead of vertical
So I have tried horizontal listview (adapter), but I cannot get the padding in the left so it will overlap each other. it's just separated like in wrap content. any suggestion on how to do this dynamically?
http://www.bild.me/bild.php?file=8656221tabs.jpg
I even tried dynamic addview
<LinearLayout
android:id="#+id/frag_productline_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
for (int i = 0 ; i < productList.size(); i++){
TextView tv = new TextView(context);
tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT) );
tv.setPadding(-40, 0, 0, 0);
tv.setText(productList.get(i));
tv.setBackgroundResource(R.drawable.tab);
layout.addView(tv);
}
But it looks like just an adapter I've tried in horizontal list view . Even worse with no handling of onItemClickListener
I suggest having an absolute layout/relative layout and scroll view instead of horizontal list view. Programmatically append the image buttons in an overlapped manner.
You can't overlap views by setting a negative padding. However, you can give them a negative margin.
LayoutParams lp = tv.getLayoutParams();
lp.setMargin(negative left margin, top, right, bottom);
tv.setLayoutParams(lp);
I am adding views dynamically in a linear layout as follows:
xml:
<LinearLayout
android:id="#+id/part1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:orientation="horizontal" >
</LinearLayout>
java:
View linearLayout = findViewById(R.id.part1);
((LinearLayout) linearLayout).removeAllViews();
for (int i = 0; i < 15; i ++){
TextView tv = new TextView(this);
tv.setText(String.valueOf(i));
LinearLayout.LayoutParams lay = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(lay);
tv.setBackgroundResource(R.drawable.msg);
tv.setId(i);
((LinearLayout) linearLayout).addView(tv);
}
Now i have two questions:
1) the text views are added horizontally correctly but if not fitting screensize, some of them won't appear, how to force it to continue adding in a new line once the horizontal space is full ?
2) textviews are added from left to right, how to add them from right to left ?
thanks
You need to understand how ViewGroups work, in this case, LinearLayout will add items horizontally or vertically without making position calculations for you unless you explicitly specify (jumping to next line is not one of them...), think of it as an item holder that will show items only on the space you specify for it (thats why some of the elements disappear...), by default the way LinearLayout arrange items is from left to right or up to down, if this do not fit your needs, you could go for any of the ViewGroup options android has, the most important might be:
RelativeLayout
FrameLayout
TableLayout
AbsoluteLayout(not recommended)
If you need some sort of Free Draw on the screen, you can always go for a View object, override onDraw, and play with the canvas of that object...
Regards!
I am using linear layout with 2 textviews, 4 buttons, 1 seekbar,1 image view. If I am place those textviews,buttons, etc. in a linear layout the alignment is fine in android phone. While I am running the same code in android tablet, alignment is not proper. Why this alignment is not proper in tablet.? I have created the textviews,buttons etc by java code. Even I am specifying the two text views horizontally by settings the left margin of the second text view by devicewidth/2 having the difference in android phone and tablet. I need to align like the below.
TextView1 TextView2
Button1 Button2 Button3 Button4 SeekBar ImageView
Here is my code.
LinearLayout.LayoutParams textViewParams1 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
textViewLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView TextView1=new TextView(this);
TextView1.setText("Text1");
textViewParams1.gravity=Gravity.CENTER;
textViewParams1.setMargins(60, 20, 40, 10);
textViewLayout.addView(chooseColorTextView, textViewParams1);
LinearLayout.LayoutParams textViewParams2 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView TextView2=new TextView(this);
TextView2.setText("Text2");
int width=getWindowManager().getDefaultDisplay().getWidth();
textViewParams2.gravity=Gravity.CENTER;
textViewParams2.setMargins((width/2), 20, 40, 10);
textViewLayout.addView(strokeWidthTextView, textViewParams2);
parentlinearLayout.addView(textViewLayout, textViewLayoutParams);
In the next linear layout, I have added the 4 buttons,seekbar and image view. But facing problems in alignment.
I advise to create complex layout that must be rendered on different screen sizes in XML rather than programmatically, so you can have two different main.xml in res/layout and in res/layout-large and the system would pick up the correct one depending on screen size.
Use layout_weight and weightSum in XML:
<LinearLayout android:weightSum="1" android:layout_width="match_parent" android:layout_height="wrap_content">
<!-- First column -->
<LinearLayout android:layout_weight=".5" android:layout_width="0dp" android:layout_height="wrap_content"> ... </LinearLayout>
<!-- Second column -->
<LinearLayout android:layout_weight=".5" android:layout_width="0dp" android:layout_height="wrap_content"> ... </LinearLayout>
</LinearLayout>
This will produce a dynamically resizing 2 column layout. If you want the divide shorter or longer, change .5 to .3 and .7 for a 30/70% split etc.
Please read more about wrap_content and other android controls. Also read about dpi of tablets. Due to resolution appearance changes.
Why don't you use a TableLayout ? its the one you need to manage cells alignement:
All that you need is in the span attribute to make cells use multiple columns.
TableLayout myLayout = new TableLayout(myContext);
TableRow row1 = new TableRow(myContext);
TableRow.LayoutParams layouparams1 = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT,TableRow.LayoutParams.WRAP_CONTENT);
layouparams1.span = 4;
row1.setLayoutParams = layouparams1 ;
TableRow.LayoutParams layouparams2 = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT,TableRow.LayoutParams.WRAP_CONTENT);
layouparams2.span = 2;
TableRow row2 = new TableRow(myContext);
row2.setLayoutParams = layouparams2 ;
//then create and add your childs to each row :
...
row1.addView(text1);
row1.addView(text1);
row1.addView(button1);
row1.addView(button2);
row1.addView(button3);
row1.addView(button4);
row1.addView(seekbar);
row1.addView(imageView);
myLayout.addView(row1);
myLayout.addView(row2);
also consider adding layout_weight on children to manage the space they left to each other.
I have TextView added Programmatically in to LinearLayout and on some external events I want to decrease bottom margin of that TextView to -10, for that I tried following.
LinearLayout.LayoutParams lastTxtParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lastTxtParams.setMargins(0, 0, 0, -10);
mOldTextView.setLayoutParams(lastTxtParams);
mOldTextView.invalidate();
Is the right way of modifying Margin of widget that has been added to View?
Some how it is not working.
TextView forgot_pswrd = (TextView) findViewById(R.id.ForgotPasswordText);
forgot_pswrd.setOnTouchListener(this);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
llp.setMargins(50, 0, 0, 0); // llp.setMargins(left, top, right, bottom);
forgot_pswrd.setLayoutParams(llp);
I did this and it worked perfectly.
Maybe as you are giving the value in -ve, that's why your code is not working.
You just put this code where you are creating the reference of the view.
Your layout in xml probably already has a layout_margin(Left|Right|etc) attribute in it, which means you need to access the object generated by that xml and modify it.
I found this solution to be very simple:
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) mTextView
.getLayoutParams();
mlp.setMargins(adjustmentPxs, 0, 0, 0);
break;
Get the LayoutParams instance of your textview, downcast it to MarginLayoutParams, and use the setMargins method to set the margins.
This one is tricky problem, i set margin to textview in a row of a table layout.
see the below:
TableLayout tl = new TableLayout(this);
tl.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
TableRow tr = new TableRow(this);
tr.setBackgroundResource(R.color.rowColor);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(4, 4, 4, 4);
TextView tv = new TextView(this);
tv.setBackgroundResource(R.color.textviewColor);
tv.setText("hello");
tr.addView(tv, params);
TextView tv2 = new TextView(this);
tv2.setBackgroundResource(R.color.textviewColor);
tv2.setText("hi");
tr.addView(tv2, params);
tl.addView(tr);
setContentView(tl);
the class needed to import for LayoutParams for use in a table row is :
import android.widget.**TableRow**.LayoutParams;
important to note that i added the class for table row. similarly many other classes are available to use LayoutParams like:
import android.widget.**RelativeLayout**.LayoutParams;
import android.widget.LinearLayout.LayoutParams;
so use accordingly.
setMargins() sets the INNER margins of the TextView, not the layout-margins. Is that what you want to do? This two different margins can be quite complicated.
If you want to set the layout margins, change the LayoutParams of the TextView (textview.getLayoutParams(), then change the parameters on the returned LayoutParams object).
You don't need to change anything on your LinearLayout.
Regards,
Oliver
TextView does not support setMargins. Android docs say:
Even though a view can define a padding, it does not provide any support for margins. However, view groups provide such a support. Refer to ViewGroup and ViewGroup.MarginLayoutParams for further information.
Here is another approach...
When I've got to the same problem, I didn't like the suggested solutions here.
So, I've come up with another way:
I've inserted a TextView in the XML file between the two fields I wanted to separate with two important fields:
visibility set to "GONE" (doesn't occupy any space..)
height is set to whatever I needed the separation to be.
XML:
...//some view up here
<TextView
android:id="#+id/dialogSeparator"
android:layout_width="match_parent"
android:layout_height="30dp"
android:visibility="gone"/>
...//some view down here
Now, I the code, all I needed to do it simple change the visibility to invisible (i.e. it's there, and taking the needed space, but it's unseen)
JAVA:
TextView tvSeparator = (TextView)activity.findViewById(R.id.dialogSeparator);
tvSeparator.setVisibility(View.INVISIBLE);
//Inside an activity extended class I can use 'this' instead of 'activity'.
Viola...I got the needed margin.
BTW, This solution is for LinearLayout with vertical orientation, but you can do it with different layouts.
Hope this helps.
You were probably changing the layout margin after it has been drawn. mOldTextView.invalidate() is useless. you needed to call requestLayout() on the parent to relayout the new configuration. When you moved the layout changing code before the drawing took place, everything worked fine.
TextView tv = (TextView)findViewById(R.id.item_title));
RelativeLayout.LayoutParams mRelativelp = (RelativeLayout.LayoutParams) tv
.getLayoutParams();
mRelativelp.setMargins(DptoPxConvertion(15), 0, DptoPxConvertion (15), 0);
tv.setLayoutParams(mRelativelp);
private int DptoPxConvertion(int dpValue)
{
return (int)((dpValue * mContext.getResources().getDisplayMetrics().density) + 0.5);
}
getLayoutParams() of textview should be casted to the corresponding Params based on the Parent of the textview in xml.
<RelativeLayout>
<TextView
android:id="#+id/item_title">
</RelativeLayout>
To render the same real size on different devices use DptoPxConvertion() method which I have used above. setMargin(left,top,right,bottom) params will take values in pixel not in dp. For further reference see this Link Answer