Comment redimensionner une vue personnalisée par programmation?

164

Je suis en train de coder une vue personnalisée, étendue de RelativeLayout, et je souhaite la redimensionner par programmation, comment puis-je faire?

la classe de vue personnalisée est quelque chose comme:

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
la source

Réponses:

253

Android lève une exception si vous ne parvenez pas à transmettre la hauteur ou la largeur d'une vue. Au lieu de créer un nouvel objet LayoutParams, utilisez celui d'origine afin que tous les autres paramètres définis soient conservés. Notez que le type de LayoutParams renvoyé par getLayoutParams est celui de la mise en page parent et non de la vue que vous redimensionnez.

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
smisiewicz
la source
2
Comme le mentionne @HerbertD, j'obtiens également une erreur en le faisant, sauf si j'utilise LinearLayout.LayoutParams, même si c'est un RelativeLayout que je redimensionne.
Martin Belcher - AtWrk
6
@Eigo Selon la documentation Android, les LayoutParams sont passés à la vue parente, car c'est la vue qui est responsable de la mise en page.
sstn
1
Si la valeur in doit être convertie en valeur dp ou cela fonctionnerait.
Dory
Ceci est également préférable car cela évite d'instancier inutilement un nouvel objet LayoutParams
Stephen Kidson
129
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

Problème résolu!

REMARQUE: assurez-vous d'utiliser la mise en page parent LayoutParams. Le mien est LinearLayout.LayoutParams!

herbertD
la source
3
Wut. Pourquoi ne pas utiliserRelativeLayout.LayoutParams?
nmr
1
Cela n'a pas fonctionné pour moi, j'ai eu une exception de distribution de classe pour cela.
Tapan Thaker
4
@Tapan Thanker Utilisez les LayoutParams de la mise en page Parent. Et la disposition My Parent est LinearLayout.
herbertD
10
J'ai écrit une version plus générique de ceci: 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
Cela réinitialisera tous les autres paramètres aux valeurs par défaut. La réponse @smisiewicz est meilleure.
Fran Marzoa
66

Cela fonctionne pour moi:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
Sileria
la source
7
C'est bien mieux que les autres réponses car ce code ne nécessite pas de connaître le type exact du ViewGroup parent.
Bart Burg
1
Savez-vous quelle est la différence entre l'appel de requestLayout () et l'appel de setLayoutParams (params)?
voghDev
2
setLayoutParams (params) inclut requestLayout ().
illusionJJ
44

Pour ce que ça vaut, disons que vous vouliez redimensionner la vue en pixels indépendants de l'appareil ( dp ): -

Vous devez utiliser une méthode appelée applyDimension, qui est membre de la classe TypedValuepour convertir des pixels en dps. Donc, si je veux régler la hauteur à 150dp (disons) - alors je pourrais faire ceci:

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

où l'expression: getResources().getDisplayMetrics()obtient la densité / résolution de l'écran

Danield
la source
6
Au lieu de coder en dur votre dimension, vous pouvez également l'utiliser pour la hauteur en pixel:float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);
Francois Dermu
cette réponse est plus appropriée comme réponse correcte !. Merci
Yunus Kulyyev
19

Dans Kotlin, vous pouvez utiliser les extensions ktx :

yourView.updateLayoutParams {
   height = <YOUR_HEIGHT>
}
Phil
la source
2
C'est génial!
user1032613
6

essayez celui-ci:

...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
zed_0xff
la source
Désolé, je n'ai pas posté toutes les questions depuis que vous y avez répondu. Voilà toute la question. Merci!
herbertD
6

Voici une version plus générique de la solution ci-dessus 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
la source
@atroutt, vous avez littéralement sauvé ma journée :)
Qasim
5

J'ai utilisé cette méthode pour augmenter la largeur de la vue personnalisée

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
la source
4

Je l'ai résolu de cette façon .. J'ai fondamentalement une vue simple à l'intérieur du fichier xml.

 View viewname = findViewById(R.id.prod_extra);
             prodExtra.getLayoutParams().height=64;
Applis DazzleGifts
la source
2
haha, méthode très naïve mais qui fonctionne bien, cependant je recommande d'appeler setLayoutParams () éventuellement pour propager correctement les modifications aux enfants imbriqués possibles, donc après la mise à jour de .width et .height, appelez view.setLayoutParams (view.getLayoutParams ()) c'est aussi toujours dactylographier
comeGetSome
@Bhargav Rao pourriez-vous m'aider sur ce sujet: https://stackoverflow.com/q/44259342/6596724
tux-world
2

Si vous avez seulement, two or three condition(sizes)vous pouvez utiliser @Overide onMeasure comme

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

Et modifiez facilement votre taille pour ces conditions dans la classe CustomView.

Xar-e-ahmer Khan
la source
1

si vous remplacez onMeasure, n'oubliez pas de mettre à jour les nouvelles tailles

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

C'est ainsi que j'ai réalisé cela. Dans réponse de Sileria, il / elle a fait ce qui suit:

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

C'est correct, mais il s'attend à ce que nous donnions la hauteur en pixels , mais je voulais donner dpla hauteur que je veux donc j'ai ajouté:

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

Cela ressemblera donc à ceci:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
Classe A
la source
0

C'est ce que j'ai fait:

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

S'il existe un groupe de vues auquel appartient cette vue, vous devrez peut-être également appeler yourViewGroup.requestLayout () pour qu'il prenne effet.

us_david
la source