Impostare i margini in un LinearLayout a livello di codice


266

Sto cercando di usare Java ( non XML ) per creare un LinearLayout con pulsanti che riempiono lo schermo e hanno margini. Ecco il codice che funziona senza margini:

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

Quindi funziona benissimo, ma come diavolo dai i margini ai pulsanti in modo che ci sia spazio tra loro? Ho provato a usare LinearLayout.MarginLayoutParams, ma questo non ha weightmembri quindi non va bene. E non funziona neanche se lo passi lpnel suo costruttore.

È impossibile? Perché sembra sicuro, e non sarebbe la prima attività di layout Android che puoi fare solo in XML.


1
developer.android.com/reference/android/view/… , int, int, int) Invece di layoutParams.setMargins (30, 20, 30, 0); inserisci layoutParams.setMargins (30dp, 20dp, 30dp, 0dp);
DarthestVader

3
setMargins prende int come argomenti .. puoi solo fornire "dp" usando gli attributi xml
jyavenard

Risposte:


496

Ecco un piccolo codice per realizzarlo:

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

6
grazie per un esempio di codice puntuale - molto più vantaggioso delle semplici descrizioni
Someone Somewhere

25
Sembra che i parametri del margine siano impostati in pixel. Un modo per impostarli in dps?
Artem Russakovskii,

30
@ArtemRussakovskii Come la maggior parte delle funzioni in Android, prendono pixel. Suggerisco una funzione di utilità globale che converte i tuffi in px. Questo è quello che ho fatto in tutte le mie app. API Android fa schifo.
MXC

7
@MaxHowell Questo è quello che ho finito per fare. È incredibile che a volte manchino cose di base come quelle.
Artem Russakovskii,

5
@ArtemRussakovskii: utilizzare TypedValue.applyDimension (...) per convertire DIP in PX. Vedi stackoverflow.com/questions/2238883/…
Gautam

64

Quindi funziona benissimo, ma come diavolo dai i margini ai pulsanti in modo che ci sia spazio tra loro?

Si chiama setMargins()l' LinearLayout.LayoutParamsoggetto.

Ho provato a usare LinearLayout.MarginLayoutParams, ma quello non ha un membro di peso quindi non va bene.

LinearLayout.LayoutParamsè una sottoclasse di LinearLayout.MarginLayoutParams, come indicato nella documentazione .

È impossibile?

No.

non sarebbe la prima attività di layout Android che puoi eseguire solo in XML

Sei il benvenuto a fornire prova di questo reclamo.

Personalmente, non sono a conoscenza di nulla che possa essere realizzato solo tramite XML e non tramite i metodi Java nell'SDK. In effetti, per definizione, tutto deve essere fattibile tramite Java (sebbene non necessariamente tramite metodi raggiungibili dall'SDK), poiché XML non è un codice eseguibile. Ma, se sei a conoscenza di qualcosa, segnalalo, perché è un bug nell'SDK che dovrebbe essere risolto un giorno.


2
Ah, ok ho capito ora. Mi stavo perdendo un po 'nel sistema di layout che è piuttosto complicato. Non credo ci sia comunque modo di impostare layout_widgth / height in fase di esecuzione.
Timmmm,

2
E non c'è modo per impostare lo stile: stackoverflow.com/questions/2016249/...
Timmmm

1
Non ho avuto problemi con l'impostazione di larghezza e altezza in fase di esecuzione tramite LayoutPararms. I termini degli stili ... sì, beh, c'è un motivo per cui non li uso. :-)
Commons War

6
Voglio sapere perché è così PITA generare a livello di codice un'interfaccia utente
Someone Somewhere

3
Mi ci sono voluti anni per rendermi conto che, qualche giorno fa, ho importato LayoutParams errati che non supportavano Margini ... Leggendo queste risposte ho deciso di rimuovere la mia importazione. Ci sono oltre 10 opzioni D: Sono andato per linearLayout.LayoutParams. Lavori.
Doomsknight,

31

Per aggiungere i margini direttamente agli elementi (alcuni elementi consentono la modifica diretta dei margini), è possibile effettuare:

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

... funziona senza la necessità di conoscere / modificare il layout circostante. Nota il controllo "instanceof" nel caso in cui provi a eseguirlo su qualcosa che non supporta i margini.


2
È esattamente quello che sto cercando.
djdance,

21

A causa della variazione delle densità dei pixel dello schermo del dispositivo, è consigliabile utilizzare sempre l' DIPunità per impostare il margine a livello di codice. Come sotto_

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

Spero che questo possa aiutare.


10

Ho impostato i margini direttamente utilizzando il codice seguente

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

L'unica cosa qui è notare che LayoutParamsdovrebbe essere importato per il seguente pacchetto android.widget.RelativeLayout.LayoutParams, altrimenti ci sarà un errore.


7

Prova questo

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

7
 MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
 layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);

2
"Sebbene questo codice possa rispondere alla domanda, è meglio includere qui la spiegazione del codice.
xenteros,

4

Prova questo:

MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.width = 250;
params.leftMargin = 50;
params.topMargin = 50;

3
/*
 * invalid margin
 */
private void invalidMarginBottom() {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) frameLayoutContent.getLayoutParams();
    lp.setMargins(0, 0, 0, 0);
    frameLayoutContent.setLayoutParams(lp);
}

dovresti essere a conoscenza del tipo di viewGroup della vista. Nel codice sopra, ad esempio, voglio cambiare il margine del frameLayout, e il gruppo di vista del frameLayout è un RelativeLayout, quindi devi convertire in (RelativeLayout.LayoutParams)


0

Ecco una soluzione a linea singola:

((LinearLayout.LayoutParams) yourLinearLayout.getLayoutParams()).marginToAdd = ((int)(Resources.getSystem().getDisplayMetrics().density * yourDPValue));
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.