W systemie Android, jak ustawić programowo marginesy w dp?


401

W ten , ten i ten wątek starałem się znaleźć odpowiedź, w jaki sposób ustawić marginesy na jednym widoku. Zastanawiałem się jednak, czy nie ma prostszego sposobu. Wyjaśnię, dlaczego wolałbym nie stosować tego podejścia:

Mam niestandardowy przycisk, który rozszerza przycisk. Jeśli tło jest ustawione na coś innego niż tło domyślne (przez wywołanie albo setBackgroundResource(int id)lub setBackgroundDrawable(Drawable d)), chcę, aby marginesy były równe 0. Jeśli wywołam to:

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

Chcę, aby marginesy zostały zresetowane do -3dp (już czytałem tutaj, jak przekonwertować z pikseli na dp, więc kiedy już wiem, jak ustawić marginesy w px, sam mogę zarządzać konwersją). Ale ponieważ jest to wywoływane w CustomButtonklasie, rodzic może różnić się od LinearLayout do TableLayout i wolałbym, aby nie pobierał jego rodzica i nie sprawdzał instancji tego rodzica. Wyobrażam sobie, że to również będzie nieskuteczne.

Ponadto, podczas wywoływania (przy użyciu LayoutParams) parentLayout.addView(myCustomButton, newParams), nie wiem, czy to dodaje go do prawidłowej pozycji (nie próbowałem jednak), powiedz środkowy przycisk z rzędu pięciu.

Pytanie: Czy jest jakiś łatwiejszy sposób programowego ustawienia marginesu jednego przycisku niż użycie LayoutParams?

EDYCJA: Znam sposób LayoutParams, ale chciałbym rozwiązania, które pozwoli uniknąć obsługi każdego innego typu kontenera:

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

Dlatego this.getLayoutParams();zwraca ViewGroup.LayoutParams, które nie posiadają atrybuty topMargin, bottomMargin, leftMargin, rightMargin. Instancja MC, którą widzisz, to po prostu MarginContainermargines przesunięcia (-3dp) i (oml, omr, omt, omb) oraz oryginalne marginesy (ml, mr, mt, mb).

Odpowiedzi:


797

Należy użyć, LayoutParamsaby ustawić marginesy przycisków:

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

W zależności od używanego układu należy użyć RelativeLayout.LayoutParamslub LinearLayout.LayoutParams.

Aby przekonwertować miarę dp na piksele, spróbuj tego:

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

152
Z którego pakietu należy zaimportować ten konkretny LayoutParams?
stealthjong

7
setMargins użył px, a użyjesz dp, moja konwersja jest prawidłowa: dp -> px, aby ustawić prawidłową wartość marginesu.
throrin19,

6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln

15
to zależy od twojego obecnego układu. Jeśli jesteś w LinearLayout, użyj LinearLayout.LayoutParams. RelativeLayout.LayoutParams inaczej
throrin19

5
powinieneś zaimportować layoutParams, który jest twoim układem nadrzędnym np. <linearlayout><relativelayout> <gridlayout> i pracujesz z układem siatki. następnie musisz użyć relativelayout.layoutparams
Sruit A.Suk

228

LayoutParams - NIE DZIAŁA! ! !

Potrzebujesz użyć typu: MarginLayoutParams

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

Przykład kodu dla MarginLayoutParams:

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


19
Poprawnie, ale nie trzeba go cofać, zmienione parametry są automatycznie odzwierciedlane. W ten sposób możesz usunąć linię: vector8.setLayoutParams (params);
Wirsing

LayaoutParams zwykle powodują zamieszanie podczas ustawiania marginesu ... Więc ten MarginLayoutParams jest bardzo przydatny. Dzięki
Atul Bhardwaj

4
musisz ustawićLayoutParams (parametry) po zmianach marginesu
Leo Droidcoder

dzisiaj znalazłem MarginLayoutParams jako nową klasę #Dziękuję.
Tushar Pandey

Nie działa dla Buttonwidoku: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()zwracanull
Konstantin Konopko

118

Najlepszy sposób:

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

Jak wywołać metodę:

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

Mam nadzieję, że to ci pomoże.


1
Mam problem z ustawieniem setMargins (holder.vCenter, 0, 20, 0,0); w ten sposób margines zostaw po obu stronach (góra i dół) co jest nie tak z powyższymi parametrami?
Arbaz.in

1
Niesamowita idealna odpowiedź !! Dziękuję Ci!!
Sjd

33
int sizeInDP = 16;

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

Następnie

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

Lub

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

15

Oto odpowiedź typu „wszystko w jednym” z najnowszymi aktualizacjami:

Krok 1, aby zaktualizować margines

Podstawowym pomysłem jest uzyskanie marginesu, a następnie jego aktualizacja. Aktualizacja zostanie zastosowana automatycznie i nie trzeba jej cofać. Aby uzyskać parametry układu, wystarczy wywołać tę metodę:

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

LayoutParamsPochodzi z układu widoku. Jeśli widok pochodzi z układu liniowego, musisz zaimportować LinearLayout.LayoutParams. Jeśli używasz względnego układu, importu LinearLayout.LayoutParamsitp.

Teraz, jeśli ustawić margines użyciu Layout_marginLeft, Rightitp, trzeba marginesu aktualizacji w ten sposób

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

Jeśli ustawisz margines za pomocą nowego layout_marginStart, musisz zaktualizować margines w ten sposób

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

Krok 2, aby zaktualizować margines w dp

Wszystkie dwa sposoby aktualizacji marginesu powyżej są aktualizowane w pikselach. Musisz wykonać tłumaczenie dp na piksele.

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

Teraz umieść obliczoną wartość w powyższych funkcjach aktualizacji marginesów i wszystko powinno być ustawione


9

layout_margin jest ograniczeniem, które dziecko widoku przekazuje swojemu rodzicowi. Jednak rolą rodzica jest wybór, czy zezwolić na margines, czy nie. Zasadniczo, ustawiając android: layout_margin = "10dp", dziecko błaga nadrzędną grupę widoków o przydzielenie miejsca o 10dp większego niż jego rzeczywisty rozmiar. (z drugiej strony padding = „10dp” oznacza, że ​​widok potomny zmniejszy swoją zawartość o 10dp ).

W związku z tym nie wszystkie grupy ViewGroup przestrzegają marginesu . Najbardziej znanym przykładem byłby widok listy, w którym marginesy elementów są ignorowane. Przed wywołaniem setMargin()LayoutParam należy zawsze upewnić się, że bieżący widok znajduje się w grupie ViewGroup, która obsługuje margines (np. LinearLayouot lub RelativeLayout), i rzutować wynik getLayoutParams()na określone LayoutParams, które chcesz. ( ViewGroup.LayoutParamsnawet nie ma setMargins()metody!)

Poniższa funkcja powinna załatwić sprawę. Pamiętaj jednak o zastąpieniu RelativeLayout typem widoku nadrzędnego.

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

9

Ta metoda pozwoli Ci ustawić Margines w 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);
}

AKTUALIZACJA

Możesz zmienić parametr, który odpowiada Twoim potrzebom.


8

W Kotlinie będzie to wyglądać tak:

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

3

Gdy jesteś w widoku niestandardowym, możesz użyć getDimensionPixelSize(R.dimen.dimen_value), w moim przypadku, dodałem margines w LayoutParams utworzonych initmetodą.

W Kotlinie

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

w Javie:

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

1

Użyj tej metody, aby ustawić margines w 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();
    }
}

wywołaj metodę:

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

1

Do szybkiego ustawienia w jednej linii

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

ale zachowaj ostrożność w przypadku jakiegokolwiek niewłaściwego użycia LayoutParams, ponieważ nie będzie to miało ifsprawdzania wystąpienia instrukcji


1

Utworzono funkcję rozszerzenia Kotlin dla tych, którzy mogą się przydać.

Pamiętaj, aby przekazywać w pikselach, a nie dp. Miłego kodowania :)

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

W moim przykładzie programowo dodaję ImageView do LinearLayout. Ustawiłem górny i dolny margines na ImagerView. Następnie dodaj ImageView do 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);

1

Możesz użyć tej metody i umieścić statyczny dimen, taki jak 20, który konwertuje zgodnie z urządzeniem

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

0

Jak dzisiaj, najlepiej jest użyć Paris , biblioteki dostarczanej przez AirBnB.

Style można następnie zastosować w następujący sposób:

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

obsługuje również widok niestandardowy (jeśli rozszerzysz widok) za pomocą adnotacji:

@Styleable and @Style

0

Musisz zadzwonić

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

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

To, czego próbujesz użyć, to tylko getter.

Android studio pokazuje, co padding...()tak naprawdę znaczy w java:

przykład wypełnienia Obraz pokazuje, że są tylko wywołaniagetPadding...()

Jeśli chcesz dodać margines do TextView, musisz mieć 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);

Musiałem rzucić mój FrameLayoutna liniowy układ, ponieważ dziedziczy po nim i ustawiał tam marginesy, więc aktywność pojawia się tylko na części ekranu wraz z innym tłem niż oryginalne parametry układu w 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);

Żadna z pozostałych osób nie pracowała nad użyciem tej samej aktywności i zmianą marginesów w oparciu o otwarcie aktywności z innego menu! setLayoutParams nigdy dla mnie nie działał - urządzenie ulegało awarii za każdym razem. Mimo że są to liczby zakodowane na stałe - jest to tylko przykład kodu wyłącznie do celów demonstracyjnych.


-1

Możesz użyć ViewGroup.MarginLayoutParamsdo ustawienia szerokości, wysokości i marginesów

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

Gdzie metoda setMargins();przyjmuje wartości odpowiednio dla lewej, górnej, prawej, dolnej. Zgodnie z ruchem wskazówek zegara !, zaczynając od lewej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.