Wie setze ich in Android programmgesteuert Ränder in dp?

401

In diesem , diesem und diesem Thread habe ich versucht, eine Antwort darauf zu finden, wie die Ränder in einer einzelnen Ansicht festgelegt werden. Ich habe mich jedoch gefragt, ob es keinen einfacheren Weg gibt. Ich werde erklären, warum ich diesen Ansatz lieber nicht verwenden möchte:

Ich habe einen benutzerdefinierten Button, der den Button erweitert. Wenn der Hintergrund auf etwas anderes als den Standardhintergrund eingestellt ist (durch Aufrufen von entweder setBackgroundResource(int id)oder setBackgroundDrawable(Drawable d)), möchte ich, dass die Ränder 0 sind. Wenn ich dies aufrufe:

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

Ich möchte, dass die Ränder auf -3dp zurückgesetzt werden (ich habe hier bereits gelesen , wie man von Pixeln in dp konvertiert. Wenn ich also weiß, wie man Ränder in px festlegt, kann ich die Konvertierung selbst verwalten). Da dies jedoch in der CustomButtonKlasse aufgerufen wird , kann das übergeordnete Element von LinearLayout zu TableLayout variieren, und ich möchte lieber nicht, dass er sein übergeordnetes Element abruft und die Instanz dieses übergeordneten Elements überprüft. Das wird auch ziemlich unperformant sein, stelle ich mir vor.

Außerdem parentLayout.addView(myCustomButton, newParams)weiß ich beim Aufrufen (mit LayoutParams) nicht, ob dies die richtige Position hinzufügt (habe es jedoch nicht versucht), beispielsweise die mittlere Schaltfläche einer Fünferreihe.

Frage: Gibt es eine einfachere Möglichkeit, den Rand einer einzelnen Schaltfläche programmgesteuert festzulegen, als LayoutParams zu verwenden?

BEARBEITEN: Ich kenne die LayoutParams-Methode, möchte aber eine Lösung, die es vermeidet, jeden einzelnen Containertyp zu behandeln:

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

Da this.getLayoutParams();kehrt ein ViewGroup.LayoutParams, die nicht die Eigenschaften haben topMargin, bottomMargin, leftMargin, rightMargin. Die mc-Instanz, die Sie sehen, ist nur eine, MarginContainerdie versetzte (-3dp) Ränder und (oml, omr, omt, omb) und die ursprünglichen Ränder (ml, mr, mt, mb) enthält.

Stealthjong
quelle

Antworten:

797

Sie sollten verwenden LayoutParams, um Ihre Schaltflächenränder festzulegen:

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

Je nachdem, welches Layout Sie verwenden, sollten Sie RelativeLayout.LayoutParamsoder verwenden LinearLayout.LayoutParams.

Versuchen Sie Folgendes, um Ihr dp-Maß in Pixel umzuwandeln:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);
throrin19
quelle
152
Aus welchem ​​Paket soll ich diese bestimmten LayoutParams importieren?
Stealthjong
7
setMargins hat px verwendet und Sie werden dp verwenden. Meine Konvertierung ist richtig: dp -> px, um den korrekten Randwert festzulegen.
Throrin19
6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln
15
Dies hängt von Ihrem aktuellen Layout ab. Wenn Sie sich in LinearLayout befinden, verwenden Sie LinearLayout.LayoutParams. RelativeLayout.LayoutParams sonst
throrin19
5
Sie sollten layoutParams importieren, das Ihr übergeordnetes Layout ist, z. <linearlayout> <relativelayout> <gridlayout> und Sie arbeiten mit dem Rasterlayout. dann müssen Sie relativelayout.layoutparams
Sruit A.Suk
228

LayoutParams - NICHT ARBEITEN! ! !

Benötigen Sie Verwendung Typ von: MarginLayoutParams

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

Codebeispiel für MarginLayoutParams:

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

Lyusten Elder
quelle
19
Richtig, aber keine Notwendigkeit, es zurückzusetzen, werden die geänderten Parameter automatisch wiedergegeben. So können Sie die Zeile entfernen: vector8.setLayoutParams (params);
Wirsing
LayaoutParams sorgen normalerweise für Verwirrung beim Festlegen des Randes ... Daher ist dieser MarginLayoutParams sehr nützlich. Vielen Dank
Atul Bhardwaj
4
Sie müssen LayoutParams (params) setzen, nachdem Sie Änderungen vorgenommen haben
Leo Droidcoder
Ich habe MarginLayoutParams heute als neue Klasse gefunden #Danke.
Tushar Pandey
Funktioniert nicht für die ButtonAnsicht: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()kehrt zurücknull
Konstantin Konopko
118

Bester Weg aller Zeiten:

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

So rufen Sie die Methode auf:

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

Hoffe das wird dir helfen.

Hiren Patel
quelle
1
Ich stehe vor einem Problem, wenn ich setMargins (Holder.vCenter, 0, 20, 0,0) setze. so ist sein Urlaubsrand auf beiden Seiten (oben und unten), was ist mit den obigen Parametern falsch?
Arbaz.in
1
Super perfekte Antwort !! Vielen Dank!!
Sjd
33
int sizeInDP = 16;

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

Dann

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

Oder

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

Hier ist die All-in-One-Antwort mit den neuesten Updates:

Schritt 1, um den Rand zu aktualisieren

Die Grundidee ist, die Marge herauszuholen und sie dann zu aktualisieren. Das Update wird automatisch angewendet und muss nicht zurückgesetzt werden. Um die Layoutparameter zu erhalten, rufen Sie einfach diese Methode auf:

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

Das LayoutParamskommt aus dem Layout Ihrer Ansicht. Wenn die Ansicht aus einem linearen Layout stammt, müssen Sie sie importieren LinearLayout.LayoutParams. Wenn Sie relatives Layout, Import LinearLayout.LayoutParamsusw. verwenden.

Nun, wenn Sie den Rand mit eingestellt Layout_marginLeft, Rightetc, müssen Sie Update - Marge auf diese Weise

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

Wenn Sie den Rand mit dem neuen festlegen layout_marginStart, müssen Sie den Rand auf diese Weise aktualisieren

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

Schritt 2, um den Rand in dp zu aktualisieren

Alle zwei oben beschriebenen Möglichkeiten zum Aktualisieren des Randes werden in Pixel aktualisiert. Sie müssen eine Übersetzung von dp in Pixel durchführen.

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

Setzen Sie nun den berechneten Wert auf die obigen Randaktualisierungsfunktionen und Sie sollten alle eingestellt sein

Fangming
quelle
9

layout_margin ist eine Einschränkung, die ein untergeordnetes Ansichtselement seinem übergeordneten Element mitteilt. Es ist jedoch die Aufgabe der Eltern, zu entscheiden, ob eine Marge zulässig ist oder nicht. Grundsätzlich fordert das Kind durch Setzen von android: layout_margin = "10dp" die übergeordnete Ansichtsgruppe auf, Speicherplatz zuzuweisen, der 10dp größer als die tatsächliche Größe ist. (padding = "10dp" bedeutet andererseits, dass die untergeordnete Ansicht ihren eigenen Inhalt um 10dp verkleinert .)

Folglich respektieren nicht alle ViewGroups die Marge . Das berüchtigtste Beispiel wäre die Listenansicht, bei der die Ränder von Elementen ignoriert werden. Bevor Sie setMargin()ein LayoutParam aufrufen, sollten Sie immer sicherstellen, dass sich die aktuelle Ansicht in einer ViewGroup befindet, die den Rand unterstützt (z. B. LinearLayouot oder RelativeLayout), und das Ergebnis getLayoutParams()in die gewünschten LayoutParams umwandeln. ( ViewGroup.LayoutParamshat nicht einmal setMargins()Methode!)

Die folgende Funktion sollte den Trick machen. Stellen Sie jedoch sicher, dass Sie RelativeLayout durch den Typ der übergeordneten Ansicht ersetzen.

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

Mit dieser Methode können Sie den Rand in DP festlegen

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

AKTUALISIEREN

Sie können den Parameter ändern, der Ihren Anforderungen entspricht.

neferpitou
quelle
8

In Kotlin wird es so aussehen:

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

Wenn Sie sich in einer benutzerdefinierten Ansicht befinden, können Sie getDimensionPixelSize(R.dimen.dimen_value)in meinem Fall den Rand in LayoutParams hinzufügen, der mit der initMethode erstellt wurde.

In 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);
    }
}
aldajo92
quelle
1

Verwenden Sie diese Methode, um den Rand in dp festzulegen

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

Rufen Sie die Methode auf:

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

Für eine schnelle einzeilige Einrichtung verwenden

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

Seien Sie jedoch vorsichtig, wenn Sie LayoutParams falsch verwenden, da dies keine ifStatment-Instanz chech enthält

Dasser Basyouni
quelle
1

Erstellt eine Kotlin-Erweiterungsfunktion für diejenigen unter Ihnen, die sie möglicherweise nützlich finden.

Stellen Sie sicher, dass Sie Pixel nicht dp übergeben. Viel Spaß beim Codieren :)

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
quelle
1

In meinem Beispiel füge ich einem LinearLayout programmgesteuert eine ImageView hinzu. Ich habe den oberen und unteren Rand auf ImagerView gesetzt. Fügen Sie dann die ImageView zum LinearLayout hinzu.



        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
quelle
1

Sie können diese Methode verwenden und statische Abmessungen wie 20 setzen, die entsprechend Ihrem Gerät konvertiert werden

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

Nach wie vor ist es wahrscheinlich am besten, Paris zu nutzen , eine von AirBnB bereitgestellte Bibliothek.

Stile können dann folgendermaßen angewendet werden:

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

Es unterstützt auch die benutzerdefinierte Ansicht (wenn Sie eine Ansicht erweitern) mithilfe von Anmerkungen:

@Styleable and @Style
sonique
quelle
0

Du musst anrufen

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

wie so: your_view.setPadding(0,16,0,0)

Was Sie versuchen zu verwenden, ist nur der Getter.

Android Studio zeigt, was padding...()in Java eigentlich bedeutet:

Auffüllbeispiel Das Bild zeigt, dass nur Anrufe getätigt werdengetPadding...()

Wenn Sie Ihrer Textansicht einen Rand hinzufügen möchten, müssen Sie LayoutParams ausführen:

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
quelle
-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

Ich musste meine FrameLayoutfür ein lineares Layout umwandeln, da es davon erbt, und dort Ränder festlegen, damit die Aktivität nur auf einem Teil des Bildschirms zusammen mit einem anderen Hintergrund als den ursprünglichen Layoutparametern im angezeigt wird 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);

Keiner der anderen arbeitete daran, dieselbe Aktivität zu verwenden und die Ränder zu ändern, indem die Aktivität aus einem anderen Menü geöffnet wurde! setLayoutParams hat bei mir nie funktioniert - das Gerät stürzte jedes Mal ab. Obwohl es sich um fest codierte Zahlen handelt, ist dies nur ein Beispiel für den Code, der nur zu Demonstrationszwecken dient.

ali mcnamara
quelle
-1

Sie können ViewGroup.MarginLayoutParamsdamit Breite, Höhe und Ränder einstellen

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

Dabei nimmt die Methode setMargins();Werte für links, oben, rechts und unten an. Im Uhrzeigersinn!, Von links beginnend.

mmmcho
quelle