In Android, come posso impostare i margini in dp a livello di codice?


402

In questo , questo e questo thread ho cercato di trovare una risposta su come impostare i margini in un'unica vista. Tuttavia, mi chiedevo se non ci fosse un modo più semplice. Spiegherò perché preferirei non usare questo approccio:

Ho un pulsante personalizzato che estende il pulsante. Se lo sfondo è impostato su un valore diverso da quello predefinito (chiamando uno setBackgroundResource(int id)o setBackgroundDrawable(Drawable d)), voglio che i margini siano 0. Se chiamo questo:

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

Voglio ripristinare i margini a -3dp (ho già letto qui come convertire da pixel a dp, quindi una volta che so come impostare i margini in px, posso gestire da solo la conversione). Ma dal momento che questo viene chiamato nella CustomButtonclasse, il genitore può variare da LinearLayout a TableLayout, e preferirei non fargli ottenere il suo genitore e controllare l'istanza di quel genitore. Sarà anche abbastanza inefficiente, immagino.

Inoltre, quando chiami (usando LayoutParams) parentLayout.addView(myCustomButton, newParams), non so se questo lo aggiunge alla posizione corretta (non ho provato comunque), dire il pulsante centrale di una riga di cinque.

Domanda: esiste un modo più semplice per impostare il margine di un singolo pulsante a livello di codice oltre all'uso di LayoutParams?

EDIT: conosco il modo LayoutParams, ma vorrei una soluzione che eviti di gestire ogni diverso tipo di contenitore:

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

Perché this.getLayoutParams();restituisce una ViewGroup.LayoutParams, che non hanno gli attributi topMargin, bottomMargin, leftMargin, rightMargin. L'istanza mc che vedi è solo una MarginContainerche contiene i margini di offset (-3dp) e (oml, omr, omt, omb) e i margini originali (ml, mr, mt, mb).

Risposte:


798

È necessario utilizzare LayoutParamsper impostare i margini dei pulsanti:

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

A seconda del layout che stai usando, dovresti usare RelativeLayout.LayoutParamso LinearLayout.LayoutParams.

E per convertire la tua misura dp in pixel, prova questo:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);

152
Da quale pacchetto devo importare quel particolare LayoutParams?
stealthjong,

7
setMargins ha utilizzato px e utilizzerai dp, la mia conversione è corretta: dp -> px per impostare il valore di margine corretto.
throrin19,

6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln

16
dipende dal layout attuale. Se sei in LinearLayout, usa LinearLayout.LayoutParams. RelativeLayout.LayoutParams altrimenti
throrin19

5
dovresti importare layoutParams che è il tuo layout genitore ex. <linearlayout><relativelayout> <gridlayout> e stai lavorando con il layout della griglia. quindi, è necessario utilizzare relativelayout.layoutparams
Sruit A.Suk

228

LayoutParams - NON FUNZIONANTE! ! !

È necessario utilizzare il tipo di: MarginLayoutParams

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

Esempio di codice per MarginLayoutParams:

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


19
Corretto, ma non è necessario ripristinarlo, i parametri modificati si riflettono automaticamente. Quindi puoi rimuovere la linea: vector8.setLayoutParams (params);
Wirsing il

LayaoutParams di solito crea confusione durante l'impostazione del margine ... Quindi questo MarginLayoutParams è molto utile. Grazie
Atul Bhardwaj il

4
devi impostare LayoutParams (parametri) dopo aver modificato le modifiche
Leo Droidcoder il

ho trovato MarginLayoutParams come nuova classe oggi #Grazie.
Tushar Pandey,

Non funziona per la Buttonvista: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()ritornanull
Konstantin Konopko

119

Il modo migliore di sempre:

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

Come chiamare il metodo:

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

Spero che questo ti possa aiutare.


1
sto riscontrando un problema quando imposto setMargins (holder.vCenter, 0, 20, 0,0); in questo modo il suo margine di congedo su entrambi i lati (in alto e in basso) cosa c'è che non va nei parametri sopra?
Arbaz

1
Fantastica risposta perfetta !! Grazie!!
Sjd

33
int sizeInDP = 16;

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

Poi

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

O

LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);

15

Ecco la risposta all-in-one con gli aggiornamenti recenti:

Passaggio 1, per aggiornare il margine

L'idea di base è quella di ottenere il margine e quindi aggiornarlo. L'aggiornamento verrà applicato automaticamente e non è necessario ripristinarlo. Per ottenere i parametri di layout, è sufficiente chiamare questo metodo:

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

La LayoutParamsderiva dal layout del vostro punto di vista. Se la vista proviene da un layout lineare, è necessario importare LinearLayout.LayoutParams. Se si utilizza il layout relativo, l'importazione LinearLayout.LayoutParams, ecc.

Ora, se si imposta il margine utilizzando Layout_marginLeft, Right, ecc, è necessario margine di aggiornamento in questo modo

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

Se si imposta il margine utilizzando il nuovo layout_marginStart, è necessario aggiornare il margine in questo modo

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

Passaggio 2, per aggiornare il margine in dp

Tutti e due i modi per aggiornare il margine sopra sono l'aggiornamento in pixel. Devi fare una traduzione di dp in pixel.

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

Ora metti il ​​valore calcolato sulle funzioni di aggiornamento del margine sopra e dovresti essere tutto pronto


9

layout_margin è un vincolo che un figlio della vista dice al suo genitore. Tuttavia, è compito del genitore scegliere se consentire il margine o meno. Fondamentalmente impostando android: layout_margin = "10dp", il bambino supplica il gruppo di visualizzazione padre di allocare spazio 10dp più grande della sua dimensione reale. (padding = "10dp", d'altra parte, significa che la vista figlio ridurrà il proprio contenuto di 10dp .)

Di conseguenza, non tutti i ViewGroup rispettano il margine . L'esempio più noto sarebbe listview, in cui i margini degli elementi vengono ignorati. Prima di chiamare setMargin()un LayoutParam, dovresti sempre assicurarti che la vista corrente risieda in un ViewGroup che supporti il ​​margine (ad esempio LinearLayouot o RelativeLayout) e trasmettere il risultato getLayoutParams()ai LayoutParam specifici che desideri. ( ViewGroup.LayoutParamsnon ha nemmeno setMargins()metodo!)

La seguente funzione dovrebbe fare il trucco. Tuttavia, assicurati di sostituire RelativeLayout al tipo di vista padre.

private void setMargin(int marginInPx) {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
    lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
    setLayoutParams(lp);
}

9

Questo metodo consente di impostare il margine in 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);
}

AGGIORNARE

È possibile modificare il parametro adatto alle proprie esigenze.


8

In Kotlin sarà simile a questo:

val layoutParams = (yourView?.layoutParams as? MarginLayoutParams)
layoutParams?.setMargins(40, 40, 40, 40)
yourView?.layoutParams = layoutParams

3

Quando si è in una vista personalizzata, è possibile utilizzare getDimensionPixelSize(R.dimen.dimen_value), nel mio caso, ho aggiunto il margine in LayoutParams creato con il initmetodo.

A 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)
}

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

2

Puoi usare questo metodo e mettere un dimen statico come 20 che converte in base al tuo dispositivo

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

1

Utilizzare questo metodo per impostare il margine in 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();
    }
}

chiama il metodo:

setMargins(linearLayout,5,0,5,0);

1

Per una rapida configurazione su una riga utilizzare

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

ma sii cauto per qualsiasi uso errato di LayoutParams, poiché questo non avrà alcuna ifistanza di dichiarazione


1

Creata una funzione di estensione Kotlin per quelli di voi che potrebbero trovarla utile.

Assicurati di passare pixel non dp. Buona programmazione :)

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 }
            }
}

1

Nel mio esempio sto aggiungendo un ImageView a un LinearLayout a livello di codice. Ho impostato i margini superiore e inferiore su ImagerView. Quindi aggiungendo ImageView a 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);

0

Come oggi, il migliore è probabilmente usare Parigi , una biblioteca fornita da AirBnB.

Gli stili possono quindi essere applicati in questo modo:

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

supporta anche la vista personalizzata (se estendi una vista) usando le annotazioni:

@Styleable and @Style

0

Devi chiamare

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

così: your_view.setPadding(0,16,0,0)

Quello che stai cercando di usare è solo il getter.

Android Studio mostra cosa padding...()significa effettivamente in Java:

esempio di imbottitura L'immagine mostra che chiama sologetPadding...()

Se vuoi aggiungere un margine al tuo TextView dovrai 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

-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

Ho dovuto eseguire il cast del mio FrameLayoutper un linearLayout poiché eredita da esso e impostare i margini lì in modo che l'attività appaia solo su una parte dello schermo con uno sfondo diverso rispetto ai parametri di layout originali in 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);

Nessuno degli altri ha lavorato per utilizzare la stessa attività e modificare i margini in base all'apertura dell'attività da un menu diverso! setLayoutParams non ha mai funzionato per me: il dispositivo si arrestava in modo anomalo ogni volta. Anche se si tratta di numeri codificati, questo è solo un esempio del codice a solo scopo dimostrativo.


-1

È possibile utilizzare ViewGroup.MarginLayoutParamsper impostare larghezza, altezza e margini

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

Dove il metodo setMargins();accetta valori rispettivamente per left, top, right, bottom. In senso orario !, partendo da sinistra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.