¿Cómo cambiar el tamaño de una vista personalizada mediante programación?

164

Estoy codificando una vista personalizada, extendida desde RelativeLayout, y quiero cambiar su tamaño programáticamente. ¿Cómo puedo hacerlo?

la clase de vista personalizada es algo así como:

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);
        }
herbertD
fuente

Respuestas:

253

Android lanza una excepción si no pasa el alto o el ancho de una vista. En lugar de crear un nuevo objeto LayoutParams, use el original para que se conserven todos los demás parámetros establecidos. Tenga en cuenta que el tipo de LayoutParams devuelto por getLayoutParams es el diseño primario , no la vista que está redimensionando.

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
smisiewicz
fuente
2
Como @HerbertD menciona, también recibo un error al hacer esto a menos que use LinearLayout.LayoutParams, incluso a través de un RelativeLayout que estoy redimensionando.
Martin Belcher - AtWrk el
66
@Eigo De acuerdo con la documentación de Android, los LayoutParams se pasan a la Vista principal, ya que esta es la vista responsable del diseño.
sstn
1
Si el valor de entrada debe convertirse en valor dp o funcionaría.
Dory
Esto también es preferible ya que evita crear instancias innecesarias de un nuevo objeto LayoutParams
Stephen Kidson
129
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

¡Problema resuelto!

NOTA: asegúrese de utilizar el diseño principal LayoutParams. El mío es LinearLayout.LayoutParams!

herbertD
fuente
3
Wut ¿Por qué no RelativeLayout.LayoutParams?
usarías
1
Esto no funcionó para mí, obtuve una excepción de reparto de clase.
Tapan Thaker
44
@Tapan Thanker Use los LayoutParams del diseño primario. Y el diseño de Mi padre es LinearLayout.
herbertD
10
Escribí una versión más genérica de esto: 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
2
Esto restablecerá todos los demás parámetros a los valores predeterminados. La respuesta de @smisiewicz es mejor.
Fran Marzoa
66

Esto funciona para mi:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
Sileria
fuente
77
Esto es mucho mejor que las otras respuestas porque este código no requiere conocer el tipo exacto del ViewGroup primario.
Bart Burg
1
¿Sabes cuál es la diferencia entre llamar a requestLayout () y llamar a setLayoutParams (params)?
voghDev
2
setLayoutParams (params) incluye requestLayout ().
illusionJJ
44

Por lo que vale, digamos que desea cambiar el tamaño de la vista en píxeles independientes del dispositivo ( dp ): -

Debe usar un método llamado applyDimension, que es miembro de la clase TypedValuepara convertir de píxeles a dps. Entonces, si quiero establecer la altura en 150dp (por ejemplo), entonces podría hacer esto:

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);

donde la expresión: getResources().getDisplayMetrics()obtiene la densidad / resolución de la pantalla

Danield
fuente
66
En lugar de codificar su dimensión, también puede usar esto para la altura en píxeles:float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);
Francois Dermu
¡Esta respuesta es más apropiada como respuesta correcta! Gracias
Yunus Kulyyev
19

En Kotlin, puede usar las extensiones ktx :

yourView.updateLayoutParams {
   height = <YOUR_HEIGHT>
}
Phil
fuente
2
¡Esto es asombroso!
user1032613
6

prueba este:

...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
zed_0xff
fuente
Lo siento, no he publicado todas las preguntas desde que lo respondiste. Ahora esa es toda la pregunta. ¡Gracias!
herbertD
6

Aquí hay una versión más genérica de la solución anterior de @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
fuente
@atroutt, literalmente me salvaste el día :)
Qasim
5

Utilicé esta manera para aumentar el ancho de la vista personalizada

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
fuente
4

Lo resolví de esta manera ... Básicamente tengo una vista simple dentro del archivo xml.

 View viewname = findViewById(R.id.prod_extra);
             prodExtra.getLayoutParams().height=64;
DazzleGifts Apps
fuente
2
jaja, muy ingenuo pero funciona bien, sin embargo, recomiendo llamar a setLayoutParams () para propagar adecuadamente el cambio a posibles hijos anidados, así que después de actualizar .width y .height, llame a view.setLayoutParams (view.getLayoutParams ()) esto también es siempre escriba prueba
comeGetSome
@Bhargav Rao podría ayudarme en este tema: https://stackoverflow.com/q/44259342/6596724
tux-world
2

Si solo two or three condition(sizes)tienes, puedes usar @Overide onMeasure como

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

Y cambie su tamaño para estas condiciones en la clase CustomView fácilmente.

Xar-e-ahmer Khan
fuente
1

si está anulando onMeasure, no olvide actualizar los nuevos tamaños

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(newWidth, newHeight);
}
XurajB
fuente
1

Así es como lo logré. En la respuesta de Sileria , hizo lo siguiente:

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

Esto es correcto, pero espera que demos la altura pixels, pero quería dar dpla altura que quiero, así que agregué:

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

Entonces se verá así:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
Clase A
fuente
0

Esto es lo que hice:

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

Si hay un grupo de vistas al que pertenece esta vista, es posible que también deba llamar a yourViewGroup.requestLayout () para que surta efecto.

us_david
fuente