I have one main linear layout which contains dynamically generated linear layouts. I am animating these layouts on ACTION_DOWN. But if i try to change the margin (top or bottom) of one layout, it affects other layouts as well. How to change one layouts margin without affecting others.
Any help would be rally appreciated.
Thanks.
EDIT
public View getLinearView() {
ChildLinearLayout linearLayout = new ChildLinearLayout(context);
LayoutParams layoutParams = new LayoutParams(500, 500);
linearLayout.setLayoutParams(layoutParams);
linearLayout.setBackgroundColor(Color.RED);
layoutParams.setMargins(20, 20, 20, 20);
layoutParams.gravity = Gravity.CENTER_HORIZONTAL;
TextView textView = new TextView(context);
textView.setText("Hello World");
linearLayout.addView(textView);
System.out.println("View Added");
views.add(linearLayout);
return linearLayout;
}
I think since you are calling
layoutParams.setMargins(20, 20, 20, 20)
for every dynamically generated layout, if you change these values then it will affect every one of your dynamically generated layouts.
Instead you could change your
getLinearView() method to getLinearView(int margin_value)
and every time you call this method for your dynamically generated layout, you could pass in the value you want for that particular layout.
ex:
If I have 5 layouts and I want to set margin of first one to 50 and others to 20 then
for(int i=0;i<5;i++)
{
if(i==0)
view=getLinearView(50);
else
view=getLinearView(20);
}
Related
Click here to see the image
In the profile page of my application, I want to have an interest section as shown in the image. The user has a list of interest under his profile. I want to show his/her interests inside a horizontal LinearLayout. I have created an array of TextViews and add them dynamically inside the parent LinearLayout, but I do not want to add the TextViews when there is no more space. Instead, I want to add a TextView showing the number of remaining interests.
As shown in the picture (use the image link), the user had 24 interests, 4 of them fit horizontally on the same line and last TextView(+20) shows the number of remaining interests on the same line.
String interestList[]={"Travel","Music","Photography","Sports","Dance","Animals","SciFi Movies"};
int interestWidth =0, parentWidth=interestLinearLayout.getWidth();
for(String interest: interestList) {
TextView textView = new TextView(MainActivity.this);
textView.setBackground(getResources().getDrawable(R.drawable.interests_bg));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(2,0,10,2);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(" "+interest+" ");
textView.setTextColor(getResources().getColor(R.color.white));
textView.setIncludeFontPadding(true);
interestWidth += textView.getWidth();
if(interestWidth<parentWidth) //both are 0 on first iteration of loop???
interestLinearLayout.addView(textView);
else
break;
}
You can add views dynamically but first you need a reference to the parent view to which you want to add a view.
You can do this by just using findViewById. Assuming it's a linear layout,
LinearLayout parent = findViewById(R.id.parent);
// Then create a textview
TextView textView = new TextView(this);
// Add the view to the parent
parent.addView(textView);
And that's it! To change properties about the TextView, you can use TextView getters and setters. If you want to change the margin, padding or height of width of the TextView, use LayoutParams
// Remember that I'm using LinearLayout.LayoutParams because the parent of the ttextview is a LinearLayout
LinearLayout.LayourParams params = textView.getLayoutParams();
// Remember these values are in pixels
params.height = 100;
params.width = 200;
There are tons of problems using this method, such as setting height and width in pixels instead of dps. And writing a lot of code when you could have done it in xml. You can however make this much easier by creating an xml file in your res/layout and then inflating it and finally adding it to the parent.
You can do this by -
// First get the layout inflater
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView textView = inflater.inflate(R.layout.myTextView, null);
linearLayout.addView(textView);
Finally addressing your problem about adding only enough views that the linearLayout doesn't go beyond the screen width.
The easiest solution is, to loop through the interest list and in every iteration of the loop, measure the combined width of the TextViews created and then checking whether it exceeds the width of the linearLayout.
It would look similar to this -
int combinedWidth = 0;
int linearLayoutWidth = linearLayout.getMeasuredWidth();
for(String interest : interests){
TextView view = inflater.inflate(R.layout.textview, null);
combinedWidth += textView.getMeasuredWidth();
view.setText(interest);
if(combinedWidth > linearLayoutWidth){
// No need to add more views
break;
}else{
linearLayout.addView(textView);
}
}
However, the above solution may or may not work depending on when it is executed. So post the activity code along with the xml file so that I can better answer your question.
The interestWidth and parentWidth are initially 0 because they have not been laid out when getWidth is called.
get width for dynamically created textViews
The above link helped me getting width of dynamically created textViews from interestList.
And by using ViewTreeObserver on interestLinearLayout I was able to get the width of LinearLayout after it was laid out.
Finally, the above code should be modified as below to add textViews from JAVA inside a LinearLayout.
final LinearLayout interestLinearLayout = findViewById(R.id.interests);
interestLinearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
interestLinearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
String interestList[]={"Travel","Music","Photography","Sports","Dance","Animals","SciFi Movies"};
int interestWidth =0;
int parentWidth = interestLinearLayout.getWidth(); // got width inside view tree observer for linearlayout
for(String interest: interestList) {
TextView textView = new TextView(MainActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(2,0,10,2);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(interest);
textView.setIncludeFontPadding(true);
textView.measure(0,0); //using approach mentioned in link to get width of text views
interestWidth += textView.getMeasuredWidth();
if(interestWidth<parentWidth)
interestLinearLayout.addView(textView);
else
break;
}
}
});
To create a LinearLayout,
LinearLayout layout = new LinearLayout(MainActivity.this);
To set background color of a layout,
layout.setBackgroundColor(Color.parseColor("#135517"));
To set width and height of the layout,
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(15, 5, 5, 5);
layout.setLayoutParams(params);
The orientation,
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(10, 10, 5, 5);
Then create a textview,
TextView textView = new TextView(this);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(" "your" ");
textView.setTextColor(getResources().getColor(R.color.white));
textView.setIncludeFontPadding(true);
Add the view to the parent,
layout.addView(textView);
i want to dynamically add images and textviews from database (blue on the picture). I also want it to be clickable, and that it could pass it's Id or something to the next activity. I thought of listview, but eclipse says it shouldn't be in a scrollview. So I tried creating linear layout, and inside it I tried to put another linear layouts (different orientation) containing image and textview (so like one linear layout per row). I'm not sure if I did it ok, but it only displays first image and last textview, so i guess it's not the right way.
Here's the layout image:
http://pbrd.co/R0JVKs
Here's how I add the views:
//architekti
llArchitekti = (LinearLayout) findViewById(R.id.architekt_layout);
LinearLayout llArchitekt;
ImageView arch_obr;
TextView tvArchitekt;
int i = 0;
for(String architekt : architekti){
arch_obr = new ImageView(ObjectInfo.this);
if(architekti_obrazky.size()>i && architekti_obrazky.get(i)!="no_image"){
arch_obr.setImageBitmap(BitmapFactory.decodeFile(getExternalFilesDir(null)+"/images/thumb/obr_"+architekti_obrazky.get(i)+"_1.jpg"));
}else{
arch_obr.setImageBitmap(BitmapFactory.decodeFile(getExternalFilesDir(null)+"/images/thumb/no_image.jpg"));
}
arch_obr.setPadding(8, 8, 20, 8);
arch_obr.setLayoutParams(new LayoutParams( 150 , LayoutParams.WRAP_CONTENT));
//here starts the adding part
llArchitekt = new LinearLayout(ObjectInfo.this);
llArchitekt.setOrientation(LinearLayout.VERTICAL);
llArchitekt.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
tvArchitekt = new TextView(ObjectInfo.this);
tvArchitekt.setText(architekt);
tvArchitekt.setClickable(true);
tvArchitekt.setTextSize(22);
tvArchitekt.setPadding(8, 8, 20, 8);
tvArchitekt.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
llArchitekt.addView(arch_obr);
llArchitekt.addView(tvArchitekt);
llArchitekti.addView(llArchitekt);
i++;
}
llArchitekt should be linear layout for each row, llArchitekti should be the linear layout that I add rows to.
llArchitekt - vertical
llArchitekti - horizontal
Also I'm not sure if it's possible to get some ID (ideally the one from database) from it on click.
You should use a ListView with Custom Adapter. There are many tutorials on the web:
Custom Listview Tutorial
I am killing myself with this problem so I am in desperate need of help.
I have a fragment with custom layout which is populated programmatically with linear layout which consists of an imageview and a textview.
User can dynamically change size of the fragment and here lies the problem.
I have onLayoutChange listener set on the fragment view where i change the size of the textview in respect to the size of the container and everything is correctly set when the container size changes but the views don't redraw themself and after the change all that i can see are the old views with their old width and height as if new width and height have never been applied.
I tried to invalidate the textview and i tried to call requestlayout on the parent view to no avail.
Its as if the new views are set but the old ones are shown.
Heres the code:
private void GenerateViews(View view) {
for (final Item artikl : listaArtikala) {
LinearLayout l_artikl = new LinearLayout(getActivity());
l_artikl.setPadding(10, 5, 0, 5);
final ImageView img = new ImageView(getActivity());
img.setMinimumWidth(image_width);
img.setMinimumHeight(image_height);
img.setScaleType(ScaleType.FIT_CENTER);
l_artikl.addView(img);
final TextView txv = new TextView(getActivity());
// dummy if to trigger after container size changes.
if(txv_artikl_width > 265)
txv.setWidth(300);
else
txv.setWidth(100);
txv.setWidth(300);
txv.setHeight(txv_artikl_height);
txv.setText(artikl.getName());
txv.setTextSize(15);
txv.setClickable(true);
txv.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
txv.setBackgroundColor(getResources().getColor(
R.color.LightSteelBlue));
txv.setPadding(5, 0, 10, 5);
l_artikl.addView(txv);
((ViewGroup) view).addView(l_artikl);
}
view.requestLayout();
}
All the help is appreciated.
After your if statement you reset the width of your textview:
if(txv_artikl_width > 265)
txv.setWidth(300);
else
txv.setWidth(100);
txv.setWidth(300);
You probably don't want to do that, right?
I am dynamically adding controls in my activity. simultaneously i'm adding a editbox and button, but facing some issue in image alignment.
Here is my code which ads the editText and Button and returns to the linear layout which is vertical in alignment.
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(0);
final EditText textView = new EditText(this);
textView.setLayoutParams(lparams);
textView.setSingleLine(true);
final LayoutParams lparams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
final Button button = new Button(this);
textView.setLayoutParams(lparams1);
if(id == R.id.new_alternate_number_button)
{
if(contactNumber == "")
{
textView.setHint("Enter contact Number");
}
else
{
textView.setText(contactNumber);
}
textView.setInputType(InputType.TYPE_CLASS_PHONE); //to popup numpad
}
else
{
if(contactEmailID == "")
{
textView.setHint("Enter Email ID ");
}
else
{
textView.setText(contactEmailID);
}
}
button.setBackgroundResource(R.drawable.ic_delete);
button.setBackgroundResource(R.drawable.ic_delete);
button.setOnClickListener(deleteView);
layout.addView(textView);
layout.addView(button);
textView.post(new Runnable() {
public void run() {
textView.requestFocus();
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(textView, InputMethodManager.SHOW_IMPLICIT);
}
});
return layout;
In my XML file i have declared linear layout which is vertical in alignment i.e icon should be at the end of screen and EditText should be left aligned.. also i need a space between EditText and image..
Thanks in advance
Your LayoutParams is set to WRAP_CONTENT for Width instead of FILL_PARENT (or MATCH_PARENT).
A "pattern" that I use in similar cases is that even though I'm dynamically adding a new row/section, I still keep they layout in an xml file for that row, and then I dynamically inflate and find the elements by id, and bind to them. Sort of like how we deal with List Items except in this case, you are not using a list.
By keeping the layout in the XML file, it'll be easier to prototype what you want to see, add padding etc. And you can even use a RelativeLayout if you can't get the LinearLayout to work. Again, you can do all of this in code, but doing layout in the XML offers more flexibility (and is simpler to deal with in my mind)
This how you can go about adding space between the Button and EditText:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(50, 0, 0, 0); // Adding margin to the left of your button
Button yourButton = new Button(this);
yourButton.setText("some text");
linearLayout.addView(yourButton, layoutParams);
The sequence of parameters in setMargins method:
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
Know more about setMargins method here.
Now that I realize your requirements properly (at least I guess so) I have another answer for you. Keep me updated about how it helps.
You will have to specify weight for the elements. Let's say total weightSum of your layout is 8, then if you specify weight of the EditText as 7, it will take 7/8th of the total space. And set wight of the Button as 1, so it will take 1/8th of the space. I am using 8 just as an example, you can change it to any number you want, do some trial and error see what weights are suiting your needs the best.
Also, the weights are in float, so don't forget the "f" after the number, like 1f and 7f:
(Again, I am not near my dev machine so there may be some errors. But this should work.)
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 7f);
// Last parameter 6f defines weight. So yourEditText will take 7/8th of the space
linearLayout.addView(yourEditText, layoutParams);
layoutParams = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);
// Last parameter 6f defines weight. So yourEditText will take 1/8th of the space
linearLayout.addView(yourButton, layoutParams);
Let's see how this helps. :)
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.