Sous Android, comment définir des marges dans dp par programme?

402

En cela , ceci et ce fil, j'ai essayé de trouver une réponse sur la façon de définir les marges sur une seule vue. Cependant, je me demandais s'il n'y avait pas de moyen plus simple. Je vais expliquer pourquoi je préfère ne pas utiliser cette approche:

J'ai un bouton personnalisé qui étend le bouton. Si l'arrière-plan est défini sur autre chose que l'arrière-plan par défaut (en appelant l'un setBackgroundResource(int id)ou l' autre setBackgroundDrawable(Drawable d)), je veux que les marges soient 0. Si j'appelle ceci:

public void setBackgroundToDefault() {
    backgroundIsDefault = true;
    super.setBackgroundResource(android.R.drawable.btn_default);
    // Set margins somehow
}

Je veux que les marges soient réinitialisées à -3dp (j'ai déjà lu ici comment convertir des pixels en dp, donc une fois que je sais comment définir des marges en px, je peux gérer la conversion moi-même). Mais comme cela est appelé dans la CustomButtonclasse, le parent peut varier de LinearLayout à TableLayout, et je préfère ne pas le faire chercher son parent et vérifier l'instance de ce parent. Ce sera également assez peu performant, j'imagine.

De plus, lors de l'appel (en utilisant LayoutParams) parentLayout.addView(myCustomButton, newParams), je ne sais pas si cela l'ajoute à la bonne position (je n'ai pas essayé cependant), disons le bouton central d'une rangée de cinq.

Question: Existe-t-il un moyen plus simple de définir la marge d'un seul bouton par programme en plus d'utiliser LayoutParams?

EDIT: Je connais la méthode LayoutParams, mais j'aimerais une solution qui évite de gérer chaque type de conteneur différent:

ViewGroup.LayoutParams p = this.getLayoutParams();
    if (p instanceof LinearLayout.LayoutParams) {
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof RelativeLayout.LayoutParams) {
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof TableRow.LayoutParams) {
        TableRow.LayoutParams lp = (TableRow.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
}

Parce que this.getLayoutParams();renvoie une ViewGroup.LayoutParams, qui n'ont pas les attributs topMargin, bottomMargin, leftMargin, rightMargin. L'instance mc que vous voyez est juste une MarginContainerqui contient des marges décalées (-3dp) et (oml, omr, omt, omb) et les marges d'origine (ml, mr, mt, mb).

stealthjong
la source

Réponses:

798

Vous devez utiliser LayoutParamspour définir les marges de vos boutons:

LayoutParams params = new LayoutParams(
        LayoutParams.WRAP_CONTENT,      
        LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);

Selon la mise en page que vous utilisez, vous devez utiliser RelativeLayout.LayoutParamsou LinearLayout.LayoutParams.

Et pour convertir votre mesure dp en pixel, essayez ceci:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);
throrin19
la source
152
À partir de quel package dois-je importer ce LayoutParams particulier?
stealthjong
7
setMargins a utilisé px et vous utiliserez dp, ma conversion est correcte: dp -> px pour définir la valeur de marge correcte.
throrin19
6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln
16
cela dépend de votre disposition actuelle. Si vous êtes dans LinearLayout, utilisez LinearLayout.LayoutParams. RelativeLayout.LayoutParams autrement
throrin19
5
vous devez importer layoutParams qui est votre disposition parent ex. <linearlayout><relativelayout> <gridlayout> et vous travaillez avec la disposition de la grille. ensuite, vous devez utiliser relativelayout.layoutparams
Sruit A.Suk
228

LayoutParams - NE FONCTIONNE PAS! ! !

Besoin d'un type d'utilisation de: MarginLayoutParams

MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;

Exemple de code pour MarginLayoutParams:

http://www.codota.com/android/classes/android.view.ViewGroup.MarginLayoutParams

Lyusten Elder
la source
19
Correct, mais pas besoin de le rétablir, les paramètres modifiés sont automatiquement reflétés. Ainsi, vous pouvez supprimer la ligne: vector8.setLayoutParams (params);
Wirsing
LayaoutParams crée généralement de la confusion lors de la définition de la marge ... Donc, ce MarginLayoutParams est très utile. Merci
Atul Bhardwaj
4
vous DEVEZ définir SetLayoutParams (paramètres) après les changements de
jonction
j'ai trouvé MarginLayoutParams comme nouvelle classe aujourd'hui #Merci.
Tushar Pandey
Ne fonctionne pas pour la Buttonvue: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()retournenull
Konstantin Konopko
119

La meilleure façon qui soit:

private void setMargins (View view, int left, int top, int right, int bottom) {
    if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
        ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        p.setMargins(left, top, right, bottom);
        view.requestLayout();
    }
}

Comment appeler la méthode:

setMargins(mImageView, 50, 50, 50, 50);

J'espère que cela vous aidera.

Hiren Patel
la source
1
je suis confronté à un problème lorsque je mets setMargins (holder.vCenter, 0, 20, 0,0); comme ça sa marge de sortie des deux côtés (haut et bas) qu'est-ce qui ne va pas avec les paramètres ci-dessus?
Arbaz.in
1
Réponse parfaite impressionnante !! Je vous remercie!!
Sjd
33
int sizeInDP = 16;

int marginInDp = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
                    .getDisplayMetrics());

alors

layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);

Ou

LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
sagits
la source
15

Voici la réponse tout-en-un avec les mises à jour récentes:

Étape 1, pour mettre à jour la marge

L'idée de base est d'extraire la marge, puis de la mettre à jour. La mise à jour sera appliquée automatiquement et vous n'avez pas besoin de la réinitialiser. Pour obtenir les paramètres de disposition, appelez simplement cette méthode:

LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();

Cela LayoutParamsvient de la disposition de votre vue. Si la vue provient d'une disposition linéaire, vous devez l'importer LinearLayout.LayoutParams. Si vous utilisez une disposition relative, une importation LinearLayout.LayoutParams, etc.

Maintenant, si vous définissez la marge à l' aide Layout_marginLeft, Rightetc., vous devez la marge de mise à jour de cette façon

layoutParams.setMargins(left, top, right, bottom);

Si vous définissez la marge à l'aide du nouveau layout_marginStart, vous devez mettre à jour la marge de cette façon

layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);

Étape 2, pour mettre à jour la marge en dp

Les deux façons de mettre à jour la marge ci-dessus sont la mise à jour en pixels. Vous devez faire une traduction de dp en pixels.

float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;

Maintenant, mettez la valeur calculée aux fonctions de mise à jour de la marge ci-dessus et vous devriez être prêt

Fangming
la source
9

layout_margin est une contrainte qu'un enfant de vue indique à son parent. Cependant, c'est le rôle du parent de choisir d'autoriser ou non la marge. Fondamentalement, en définissant android: layout_margin = "10dp", l'enfant plaide le groupe de vues parent pour allouer un espace qui est 10dp plus grand que sa taille réelle. (padding = "10dp", d'autre part, signifie que la vue enfant réduira son propre contenu de 10dp .)

Par conséquent, tous les ViewGroups ne respectent pas la marge . L'exemple le plus notoire serait listview, où les marges des éléments sont ignorées. Avant d'appeler setMargin()un LayoutParam, vous devez toujours vous assurer que la vue actuelle se trouve dans un ViewGroup qui prend en charge la marge (par exemple LinearLayouot ou RelativeLayout), et convertir le résultat de getLayoutParams()dans le LayoutParams spécifique de votre choix. ( ViewGroup.LayoutParamsn'a même pas de setMargins()méthode!)

La fonction ci-dessous devrait faire l'affaire. Assurez-vous toutefois de remplacer RelativeLayout par le type de la vue parent.

private void setMargin(int marginInPx) {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
    lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
    setLayoutParams(lp);
}
Ian Wong
la source
9

Cette méthode vous permettra de définir la marge dans DP

public void setMargin(Context con,ViewGroup.LayoutParams params,int dp) {

        final float scale = con.getResources().getDisplayMetrics().density;
        // convert the DP into pixel
        int pixel =  (int)(dp * scale + 0.5f); 

        ViewGroup.MarginLayoutParams s =(ViewGroup.MarginLayoutParams)params;
        s.setMargins(pixel,pixel,pixel,pixel);

        yourView.setLayoutParams(params);
}

MISE À JOUR

Vous pouvez modifier le paramètre qui convient à votre besoin.

neferpitou
la source
8

Dans Kotlin, cela ressemblera à ceci:

val layoutParams = (yourView?.layoutParams as? MarginLayoutParams)
layoutParams?.setMargins(40, 40, 40, 40)
yourView?.layoutParams = layoutParams
Morozov
la source
3

Lorsque vous êtes dans une vue personnalisée, vous pouvez utiliser getDimensionPixelSize(R.dimen.dimen_value), dans mon cas, j'ai ajouté la marge dans LayoutParams créée sur la initméthode.

À Kotlin

init {
    LayoutInflater.from(context).inflate(R.layout.my_layout, this, true)
    layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
    val margin = resources.getDimensionPixelSize(R.dimen.dimen_value)
    setMargins(0, margin, 0, margin)
}

en Java:

public class CustomView extends LinearLayout {

    //..other constructors

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        int margin = getResources().getDimensionPixelSize(R.dimen.spacing_dime);
        params.setMargins(0, margin, 0, margin);
        setLayoutParams(params);
    }
}
aldajo92
la source
2

Vous pouvez utiliser cette méthode et mettre des dimen statiques comme 20 convertis selon votre appareil

 public static int dpToPx(int dp) 
      {
          float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
  }
Dishant Kawatra
la source
1

Utilisez cette méthode pour définir la marge en dp

private void setMargins (View view, int left, int top, int right, int bottom) {
    if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
        ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();

        final float scale = getBaseContext().getResources().getDisplayMetrics().density;
        // convert the DP into pixel
        int l =  (int)(left * scale + 0.5f);
        int r =  (int)(right * scale + 0.5f);
        int t =  (int)(top * scale + 0.5f);
        int b =  (int)(bottom * scale + 0.5f);

        p.setMargins(l, t, r, b);
        view.requestLayout();
    }
}

appelez la méthode:

setMargins(linearLayout,5,0,5,0);
Ridwan Bin Sarwar
la source
1

Pour une configuration rapide sur une seule ligne, utilisez

((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);

mais faites attention à toute mauvaise utilisation de LayoutParams, car cela n'aura pas d' ifinstance de chech

Dasser Basyouni
la source
1

Création d'une fonction d'extension Kotlin pour ceux d'entre vous qui pourraient la trouver pratique.

Assurez-vous de passer en pixels et non en dp. Bon codage :)

fun View.addLayoutMargins(left: Int? = null, top: Int? = null,
                      right: Int? = null, bottom: Int? = null) {
    this.layoutParams = ViewGroup.MarginLayoutParams(this.layoutParams)
            .apply {
                left?.let { leftMargin = it }
                top?.let { topMargin = it }
                right?.let { rightMargin = it }
                bottom?.let { bottomMargin = it }
            }
}
David Kim
la source
1

Dans mon exemple, j'ajoute une ImageView à un LinearLayout par programme. J'ai défini des marges supérieure et inférieure sur ImagerView. Ensuite, en ajoutant ImageView au LinearLayout.



        ImageView imageView = new ImageView(mContext);
        imageView.setImageBitmap(bitmap);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
        );
        params.setMargins(0, 20, 0, 40);
        imageView.setLayoutParams(params);
        linearLayout.addView(imageView);
Rajeev Shetty
la source
0

Comme aujourd'hui, le mieux est probablement d'utiliser Paris , une bibliothèque fournie par AirBnB.

Les styles peuvent ensuite être appliqués comme ceci:

Paris.style(myView).apply(R.style.MyStyle);

il prend également en charge la vue personnalisée (si vous étendez une vue) à l'aide d'annotations:

@Styleable and @Style
sonique
la source
0

Vous devez appeler

setPadding(int left, int top, int right, int bottom)

ainsi: your_view.setPadding(0,16,0,0)

Ce que vous essayez d'utiliser, c'est seulement le getter.

Le studio Android montre ce que padding...()signifie réellement en java:

exemple de remplissage L'image montre qu'elle n'appelle quegetPadding...()

Si vous souhaitez ajouter une marge à votre TextView, vous devrez LayoutParams:

val params =  LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT)
params.setMargins(int left, int top, int right, int bottom)
your_view.layoutParams = params
Saadat Sayem
la source
-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

J'ai dû lancer le mien FrameLayoutpour une mise en page linéaire car il en hérite et y définir des marges afin que l'activité n'apparaisse que sur une partie de l'écran avec un arrière-plan différent de celui des paramètres de mise en page d'origine dans le setContentView.

LinearLayout linearLayout = (LinearLayout) findViewById(R.id.activity);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
linearLayout.setBackgroundColor(getResources().getColor(R.color.full_white));
setContentView(linearLayout,layoutParams);

Aucun des autres n'a travaillé pour utiliser la même activité et changer les marges en ouvrant l'activité à partir d'un menu différent! setLayoutParams n'a jamais fonctionné pour moi - le périphérique plantait à chaque fois. Même s'il s'agit de nombres codés en dur - ce n'est qu'un exemple du code à des fins de démonstration uniquement.

Ali Mcnamara
la source
-1

Vous pouvez utiliser ViewGroup.MarginLayoutParamspour définir la largeur, la hauteur et les marges

ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);

Où la méthode setMargins();prend des valeurs pour gauche, haut, droite, bas respectivement. Dans le sens horaire !, à partir de la gauche.

mmmcho
la source