Définir des marges dans un LinearLayout par programmation

266

J'essaie d'utiliser Java ( pas XML ) pour créer un LinearLayout avec des boutons qui remplissent l'écran et ont des marges. Voici du code qui fonctionne sans marges:

LinearLayout buttonsView = new LinearLayout(this);
buttonsView.setOrientation(LinearLayout.VERTICAL);
for (int r = 0; r < 6; ++r) {
    Button btn = new Button(this);
    btn.setText("A");

    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); // Verbose!
    lp.weight = 1.0f; // This is critical. Doesn't work without it.
    buttonsView.addView(btn, lp);
}

ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
setContentView(buttonsView, lp);

Donc ça marche bien, mais comment diable donnez-vous les marges des boutons pour qu'il y ait de l'espace entre eux? J'ai essayé d'utiliser LinearLayout.MarginLayoutParams, mais cela n'a pas de weightmembre donc ce n'est pas bon. Et cela ne fonctionne pas si vous le passez lpdans son constructeur non plus.

Est-ce impossible? Parce que ça y ressemble, et ce ne sera pas la première tâche de mise en page Android que vous ne pouvez faire qu'en XML.

Timmmm
la source
1
developer.android.com/reference/android/view/… , int, int, int) Au lieu de layoutParams.setMargins (30, 20, 30, 0); vous mettez layoutParams.setMargins (30dp, 20dp, 30dp, 0dp);
DarthestVader
3
setMargins prend int comme arguments .. vous ne pouvez fournir que "dp" en utilisant les attributs xml
jyavenard

Réponses:

496

Voici un petit code pour y parvenir:

LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
     LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

layoutParams.setMargins(30, 20, 30, 0);

Button okButton=new Button(this);
okButton.setText("some text");
ll.addView(okButton, layoutParams);
Mauro
la source
6
merci pour un exemple de code au point - bien plus bénéfique que de simples descriptions
Quelqu'un Quelque part
25
Il semble que les paramètres de marge soient définis en pixels. Est-il possible de les définir en dps?
Artem Russakovskii
30
@ArtemRussakovskii Comme la plupart des fonctions d'Android, elles prennent des pixels. Je suggère une fonction utilitaire globale qui convertit les creux en px. C'est ce que j'ai fait dans toutes mes applications. L'API Android craint.
mxcl
7
@MaxHowell C'est ce que j'ai fini par faire. C'est incroyable que des choses de base comme ça manquent parfois.
Artem Russakovskii
5
@ArtemRussakovskii - utilisez TypedValue.applyDimension (...) pour convertir DIP en PX. Voir stackoverflow.com/questions/2238883/…
Gautam
64

Donc ça marche bien, mais comment diable donnez-vous les marges des boutons pour qu'il y ait de l'espace entre eux?

Vous invoquez setMargins()l' LinearLayout.LayoutParamsobjet.

J'ai essayé d'utiliser LinearLayout.MarginLayoutParams, mais cela n'a pas de membre de poids donc ce n'est pas bon.

LinearLayout.LayoutParamsest une sous-classe de LinearLayout.MarginLayoutParams, comme indiqué dans la documentation .

Est-ce impossible?

Non.

ce ne serait pas la première tâche de mise en page Android que vous ne pouvez faire qu'en XML

Vous êtes invités à fournir une preuve de cette réclamation.

Personnellement, je ne suis au courant de rien qui ne peut être accompli que via XML et non via les méthodes Java du SDK. En fait, par définition, tout doit être faisable via Java (mais pas nécessairement via des méthodes accessibles par SDK), car XML n'est pas du code exécutable. Mais, si vous êtes au courant de quelque chose, signalez-le, car c'est un bogue dans le SDK qui devrait être corrigé un jour.

CommonsWare
la source
2
Ha, ok je comprends maintenant. Se perdait un peu dans le système de mise en page ce qui est plutôt compliqué. Je ne pense pas qu'il existe de toute façon de définir layout_widgth / height au moment de l'exécution.
Timmmm
2
Et il n'y a aucun moyen de définir le style: stackoverflow.com/questions/2016249/…
Timmmm
1
Je n'ai pas eu de problème avec la définition de la largeur et de la hauteur lors de l'exécution via LayoutPararms. En termes de styles ... oui, eh bien, il y a une raison pour laquelle je ne les utilise pas. :-)
CommonsWare
6
Je veux savoir pourquoi c'est un tel PITA pour générer par programme une interface utilisateur
Quelqu'un Quelque part Quelque part
3
Cela m'a pris beaucoup de temps pour réaliser que, il y a quelques jours, j'ai importé les mauvais LayoutParams qui ne prenaient pas en charge les marges ... En lisant ces réponses, j'ai décidé de supprimer mon importation. Il y a plus de 10 options D: je suis allé pour linearLayout.LayoutParams. Travaux.
Doomsknight
31

Pour ajouter des marges directement aux éléments (certains éléments permettent la modification directe des marges), vous pouvez faire:

LayoutParams lp = ((ViewGroup) something).getLayoutParams();
if( lp instanceof MarginLayoutParams )
{
    ((MarginLayoutParams) lp).topMargin = ...;
    ((MarginLayoutParams) lp).leftMargin = ...;
    //... etc
}
else
    Log.e("MyApp", "Attempted to set the margins on a class that doesn't support margins: "+something.getClass().getName() );

... cela fonctionne sans avoir besoin de connaître / modifier la disposition environnante. Notez la vérification "instanceof" au cas où vous essayez de l'exécuter sur quelque chose qui ne prend pas en charge les marges.

Adam
la source
2
C'est exactement ce que je cherche.
djdance
21

En raison de la variation des densités de pixels de l'écran de l'appareil, il est bon de toujours utiliser l' DIPunité pour définir la marge par programme. Comme ci-dessous_

//get resources
Resources r = getResources();
float pxLeftMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxTopMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxRightMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxBottomMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics());

//get layout params...
LayoutParams params=new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
params.setMargins(Math.round(pxLeftMargin), Math.round(pxTopMargin), Math.round(pxRightMargin), Math.round(pxBottomMargin));

//set margin...
yourLayoutTOsetMargin.setLayoutParams(params); 

J'espère que cela vous aidera.

Rupesh Yadav
la source
10

J'ai configuré des marges directement en utilisant le code ci-dessous

LinearLayout layout = (LinearLayout)findViewById(R.id.yourrelative_layout);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);            
params.setMargins(3, 300, 3, 3); 
layout.setLayoutParams(params);

La seule chose ici est de remarquer que cela LayoutParamsdevrait être importé pour le paquet suivant android.widget.RelativeLayout.LayoutParams, sinon il y aura une erreur.

Janith
la source
7

Essaye ça

 LayoutParams params = new LayoutParams(
            LayoutParams.WRAP_CONTENT,      
            LayoutParams.WRAP_CONTENT
    );
    params.setMargins(left, top, right, bottom);
    yourbutton.setLayoutParams(params);
Karan Bhalodiya
la source
7
 MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
 layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
Ginni
la source
2
«Bien que ce code puisse répondre à la question, il est préférable d'inclure l'explication du code ici.
xenteros
4

Essaye ça:

MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.width = 250;
params.leftMargin = 50;
params.topMargin = 50;
Makvin
la source
3
/*
 * invalid margin
 */
private void invalidMarginBottom() {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) frameLayoutContent.getLayoutParams();
    lp.setMargins(0, 0, 0, 0);
    frameLayoutContent.setLayoutParams(lp);
}

vous devez être le type de viewGroup de la vue.Dans le code ci-dessus, par exemple, je veux modifier la marge de frameLayout, et le groupe de vues de frameLayout est un RelativeLayout, vous devez donc vous convertir à (RelativeLayout.LayoutParams)

Francis Shi
la source
0

Voici une solution en ligne unique:

((LinearLayout.LayoutParams) yourLinearLayout.getLayoutParams()).marginToAdd = ((int)(Resources.getSystem().getDisplayMetrics().density * yourDPValue));
Stappo
la source