83

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.

User7723337
  • 11,857
  • 27
  • 101
  • 182

8 Answers8

189
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.

Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
Debarati
  • 3,296
  • 2
  • 18
  • 30
  • This call requires API level 19. – Sanjay Kumar Feb 14 '14 at 06:36
  • 4
    @SanjayKumar - No, there is no constraint that it requires API level 19 – Debarati Mar 06 '14 at 05:33
  • 1
    How does this answer OP's question? It seems the code is the same except for redundant extra line setting touch listener, not calling invalidate(), and not explicitly stating arguments in constructor to LinearLayout.LayoutParams [LayoutParams.WRAP_CONTENT vs LinearLayout.LayoutParams.WRAP_CONTENT]? In addition (not that it could matter), OP is asking for setting margins on programmatically created TextView, though the answer obtains TextView from layout xml, via findViewById(). I'm curious what I'm missing here... – Melquiades Mar 09 '15 at 15:14
  • @Melquiades agree with you, removed as selected answer as it does not answer the question, also as mentioned in the answer `Maybe as you are giving the value in -ve` margins can be a -ve value. – User7723337 Apr 27 '15 at 11:32
61

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.

Danny Armstrong
  • 1,320
  • 12
  • 13
10

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.

Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
Shaman Virk
  • 181
  • 2
  • 8
5

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

Oliver
  • 1,269
  • 13
  • 21
3

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.

andig
  • 13,378
  • 13
  • 61
  • 98
1

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:

  1. visibility set to "GONE" (doesn't occupy any space..)
  2. 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.

JamesC
  • 356
  • 4
  • 8
0

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.

Radu Simionescu
  • 4,518
  • 1
  • 35
  • 34
0
        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

anand krish
  • 4,281
  • 4
  • 44
  • 47