197

I am coding a custom view, extended from RelativeLayout, and I want to resize it programmatically, How can I do?

the custom view Class is something like:

public ActiveSlideView(Context context, AttributeSet attr){
        super(context, attr);
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(inflater != null){       
            inflater.inflate(R.layout.active_slide, this);
        }
weston
  • 54,145
  • 21
  • 145
  • 203
herbertD
  • 10,657
  • 13
  • 50
  • 77
  • Does this answer your question? [Set ImageView Size Programmatically in DP Java](https://stackoverflow.com/questions/35803313/set-imageview-size-programmatically-in-dp-java) – Eury Pérez Beltré Aug 17 '20 at 14:27

16 Answers16

275

Android throws an exception if you fail to pass the height or width of a view. Instead of creating a new LayoutParams object, use the original one, so that all other set parameters are kept. Note that the type of LayoutParams returned by getLayoutParams is that of the parent layout, not the view you are resizing.

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
Noah Andrews
  • 353
  • 2
  • 14
smisiewicz
  • 2,994
  • 2
  • 15
  • 12
  • 2
    As @HerbertD mentions I also get an error doing this unless I use LinearLayout.LayoutParams, even through it is a RelativeLayout that I am resizing. – Martin Belcher - AtWrk Nov 09 '11 at 12:10
  • 7
    @Eigo According to the Android documentation, the LayoutParams are passed to the parent View, as this is the view which is responsible for the layout. – sstn Nov 16 '11 at 14:01
  • 1
    Whether the in value should be converted into dp value or it would work. – Dory Nov 20 '13 at 05:28
  • This is also preferable as it avoids instantiating a new LayoutParams object unnecessarily – Stephen Kidson Dec 03 '14 at 03:14
136
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

Problem solved!

NOTE: Be sure to use the parent Layout's LayoutParams. Mine is LinearLayout.LayoutParams!

Elltz
  • 10,730
  • 4
  • 31
  • 59
herbertD
  • 10,657
  • 13
  • 50
  • 77
  • 3
    Wut. Why wouldn't you use `RelativeLayout.LayoutParams?` – nmr Sep 01 '11 at 16:44
  • 1
    This didn't work for me , i got a class cast exception for it . – Tapan Thaker Jul 06 '12 at 08:49
  • 4
    @Tapan Thanker Use the Parent layout's LayoutParams. And My Parent layout is LinearLayout. – herbertD Jul 09 '12 at 05:55
  • 10
    I wrote a more generic version of this: `private void resizeView(View view, int newWidth, int newHeight) { try { Constructor extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); view.setLayoutParams(ctor.newInstance(newWidth, newHeight)); } catch (Exception e) { e.printStackTrace(); } }` – atroutt Sep 16 '13 at 22:02
  • Why not change the params of the existing layout? `someLayout.getLayoutParams()` – AlikElzin-kilaka Jul 01 '14 at 11:40
  • You don't need to use the parent Layout's viewgroup, just do it like this: ViewGroup.LayoutParams params = layout.getLayoutParams(); – Bart Burg Feb 02 '16 at 09:19
  • @atroutt You should put that as an answer. I used that method and it worked perfectly. I'l upvote it! – Grux Mar 21 '16 at 22:59
  • As requested, posted separate answer http://stackoverflow.com/a/38250295/338642 @Grux – atroutt Jul 07 '16 at 16:07
  • Since this answer is almost 4 years old FILL_PARENT should be replaced with MATCH_PARENT – afj88 Oct 10 '18 at 14:50
  • 2
    This will reset all the other parameters to default values. @smisiewicz answer is better. – Fran Marzoa Jul 12 '19 at 09:51
74

This works for me:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
Sileria
  • 15,223
  • 4
  • 49
  • 28
51

In Kotlin, you can use the ktx extensions:

yourView.updateLayoutParams {
   height = <YOUR_HEIGHT>
}
Phil
  • 4,730
  • 1
  • 41
  • 39
50

For what it's worth, let's say you wanted to resize the view in device independent pixels (dp): -

You need to use a method called applyDimension, that's a member of the class TypedValue to convert from dp to pixels. So if I want to set the height to 150dp (say) - then I could do this:

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) someLayout.getLayoutParams();
params.height = (int) pixels;
someLayout.setLayoutParams(params);

where the expression: getResources().getDisplayMetrics() gets the screen density/resolution

Ryan M
  • 18,333
  • 31
  • 67
  • 74
Danield
  • 121,619
  • 37
  • 226
  • 255
  • 7
    Instead of hard coding your dimension you can also use this for the height in pixel: `float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);` – Francois Dermu Apr 05 '16 at 20:43
7

Here's a more generic version of the solution above from @herbertD :

private void resizeView(View view, int newWidth, int newHeight) { 
    try { 
        Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); 
        view.setLayoutParams(ctor.newInstance(newWidth, newHeight));   
    } catch (Exception e) { 
        e.printStackTrace(); 
    }
}
atroutt
  • 471
  • 6
  • 14
6

try a this one:

...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
zed_0xff
  • 32,417
  • 7
  • 53
  • 72
5

I used this way to increase width of custom view

customDrawingView.post(new Runnable() {
                            @Override
                            public void run() {
                                View view_instance = customDrawingView;
                                android.view.ViewGroup.LayoutParams params = view_instance
                                        .getLayoutParams();
                                int newLayoutWidth = customDrawingView
                                        .getWidth()
                                        + customDrawingView.getWidth();
                                params.width = newLayoutWidth;
                                view_instance.setLayoutParams(params);
                                screenWidthBackup = params.width;
                            }
                        });
AkhilGite
  • 400
  • 4
  • 17
5

With Kotlin and using dp unit:

myView.updateLayoutParams {
    val pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200f, context.resources.displayMetrics)
    height = pixels.toInt()
}
Skoua
  • 3,373
  • 3
  • 38
  • 51
4

I solved it this way.. I have basically a simple view inside xml file.

 View viewname = findViewById(R.id.prod_extra);
             prodExtra.getLayoutParams().height=64;
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
  • 2
    haha, very naive but well working way, however I recommend to call setLayoutParams() eventually to properly propagate change to possible nested children, so after updating .width and .height, call view.setLayoutParams(view.getLayoutParams()) this is also always type proof – comeGetSome Dec 02 '16 at 13:48
  • @Bhargav Rao could you help me on this topic: `https://stackoverflow.com/q/44259342/6596724` – tux-world May 30 '17 at 10:39
3

If you have only two or three condition(sizes) then you can use @Overide onMeasure like

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

And change your size for these conditions in CustomView class easily.

Xar-e-ahmer Khan
  • 1,314
  • 15
  • 23
3

This is how it can be done in Kotlin:

updateLayoutParams:

val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
            id = View.generateViewId()

            updateLayoutParams { 
                height = 200
                width = 400 
            }

        }
binding.ssss.addView(view)

OR

layoutParams:

val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
            id = View.generateViewId()
            
            layoutParams.width = 200
            layoutParams.height = 200
            
        }
binding.ssss.addView(view)
Dharman
  • 30,962
  • 25
  • 85
  • 135
2

if you are overriding onMeasure, don't forget to update the new sizes

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(newWidth, newHeight);
}
XurajB
  • 820
  • 1
  • 14
  • 29
1

This is how I achieved this. In Sileria answer he/she did the following:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();

This is correct, but it expects us to give the height in pixels, but I wanted to give the dp I want the height to be so I added:

public int convertDpToPixelInt(float dp, Context context) {
    return (int) (dp * (((float) context.getResources().getDisplayMetrics().densityDpi) / 160.0f));
}

So it will look like this:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
ClassA
  • 2,480
  • 1
  • 26
  • 57
1

This is what I did:

View myView;  
myView.getLayoutParams().height = 32;  
myView.getLayoutParams().width = 32;

If there is a view group that this view belongs to, you may also need to call yourViewGroup.requestLayout() for it to take effect.

halfer
  • 19,824
  • 17
  • 99
  • 186
us_david
  • 4,431
  • 35
  • 29
0
fun View.setSize(width: Int, height: Int) {
    updateLayoutParams {
        this.width = width
        this.height = height
    }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135