Jak ustawić margines ImageView za pomocą kodu, a nie XML

177

Chcę dodać nieznaną liczbę ImageViewwidoków do mojego układu z marginesami. W XML mogę użyć w layout_marginten sposób:

<ImageView android:layout_margin="5dip" android:src="@drawable/image" />

Jest ImageView.setPadding(), ale nie ImageView.setMargin(). Myślę, że jest to podobne ImageView.setLayoutParams(LayoutParams), ale nie jestem pewien, czym się w to karmić.

Czy ktoś wie?

Bruce Lee
źródło

Odpowiedzi:

381

android.view.ViewGroup.MarginLayoutParamsma metodę setMargins(left, top, right, bottom). Bezpośrednie podklasy to: FrameLayout.LayoutParams, LinearLayout.LayoutParamsi RelativeLayout.LayoutParams.

Używając np LinearLayout:

LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
imageView.setLayoutParams(lp);

MarginLayoutParams

To ustawia marginesy w pikselach. Aby go skalować, użyj

context.getResources().getDisplayMetrics().density

DisplayMetrics

Klucz
źródło
18
Zauważ, że to ustawia rozmiar marginesów w PIKSELACH, nie jest tym samym, co jednostka dpi w xml tego pytania.
aromero
Jak możemy użyć wartości dpi zamiast piksela?
Pascal Piché
10
Możesz skalować wartość w pikselach za pomocą context.getResources (). GetDisplayMetrics (). Density developer.android.com/reference/android/util/ ...
Klucz
1
Zauważ, że mogą być problemy z FrameLayout.LayoutParamsinnymi: stackoverflow.com/questions/5401952/…
Dmitry Zaytsev
na wypadek, gdybyśmy chcieli ustawić tylko dolny margines widoku obrazu, który jest android:layout_centerHorizontal = "true"iw android:layout_alignParentBottom = "true"jaki sposób mógłbym to osiągnąć?
ssrp
51
    image = (ImageView) findViewById(R.id.imageID);
    MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
    marginParams.setMargins(left_margin, top_margin, right_margin, bottom_margin);
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
    image.setLayoutParams(layoutParams);
Kevin Wadera
źródło
5
O co chodzi w ostatnich 2 liniach? sklonować parametry marginesu do innej zmiennej params? Potwierdzam, że jest to wymagane :)
Adam Rabung
1
na wypadek, gdybyśmy chcieli ustawić tylko dolny margines widoku obrazu, który jest android:layout_centerHorizontal = "true"iw android:layout_alignParentBottom = "true"jaki sposób mógłbym to osiągnąć?
ssrp
layoutparams.addRule (RelativeLayout.CENTER_HORIZONTAL);
cwhsu
Wymagane jest utworzenie innych parametrów układu. Dzięki :)
Muzaffer
42

Wszystkie powyższe przykłady faktycznie ZMIENI wszelkie parametry już obecne w Widoku, co może nie być pożądane. Poniższy kod po prostu rozszerzy istniejące parametry, bez ich zastępowania:

ImageView myImage = (ImageView) findViewById(R.id.image_view);
MarginLayoutParams marginParams = (MarginLayoutParams) image.getLayoutParams();
marginParams.setMargins(left, top, right, bottom);
Kelevandos
źródło
1
To pierwsze rozwiązanie na tej liście, które zadziałało dla mnie. Inni schrzanili inne parametry, które ustawiłem w XML, w tym parametry RelativeLayout do pozycjonowania.
Chris Dutrow
22

Kod Kevina tworzy nadmiarowy MarginLayoutParamsobiekt. Prostsza wersja:

ImageView image = (ImageView) findViewById(R.id.main_image);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(image.getLayoutParams());
lp.setMargins(50, 100, 0, 0);
image.setLayoutParams(lp);
Adam Stelmaszczyk
źródło
1
Co dziwne, otrzymuję wtedy komunikat „Cannot rozwiązać metodę setmargins ()”, dlatego wyszukałem w Google to pytanie i wylądowałem tutaj.
user2875404
11

Jeśli chcesz zmienić margines widoku obrazu, ale pozostałe marginesy pozostaw nienaruszone.

  1. Pobierz MarginLayoutParameters widoku obrazu w tym przypadku: myImageView

     MarginLayoutParams marginParams = (MarginLayoutParams) myImageView.getLayoutParams();
  2. Teraz po prostu zmień margines, który chcesz zmienić, ale pozostałe pozostaw bez zmian:

     marginParams.setMargins(marginParams.leftMargin, 
                             marginParams.topMargin, 
                             150, //notice only changing right margin
                             marginParams.bottomMargin); 
CommonSenseCode
źródło
8

Możesz użyć tej metody, jeśli chcesz określić marginesy w dp:

private void addMarginsInDp(View view, int leftInDp, int topInDp, int rightInDp, int bottomInDp) {
    DisplayMetrics dm = view.getResources().getDisplayMetrics();
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    lp.setMargins(convertDpToPx(leftInDp, dm), convertDpToPx(topInDp, dm), convertDpToPx(rightInDp, dm), convertDpToPx(bottomInDp, dm));
    view.setLayoutParams(lp);
}

private int convertDpToPx(int dp, DisplayMetrics displayMetrics) {
    float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
    return Math.round(pixels);
}
divonas
źródło
8

Używam po prostu tego i działa świetnie:

ImageView imageView = (ImageView) findViewById(R.id.image_id);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.setMargins(left, top, right, bottom);
imageView.setLayoutParams(layoutParams);

Jednostką setMargins () jest piksel, a nie dp. Jeśli chcesz ustawić margines w dp, po prostu w pliku values ​​/ dimens.xml utwórz wymiary takie jak:

<resources>
    <dimen name="right">16dp</dimen>
    <dimen name="left">16dp</dimen>    
</resources>

i dostęp jak:

getResources().getDimension(R.dimen.right);
Elnoor
źródło
5

Jeśli używasz kotlin, można to uprościć, tworząc funkcję rozszerzającą

fun View.setMarginExtensionFunction(left: Int, top: Int, right: Int, bottom: Int) {
  val params = layoutParams as ViewGroup.MarginLayoutParams
  params.setMargins(left, top, right, bottom)
  layoutParams = params
}

Teraz wszystko, czego potrzebujesz, to widok, a tej funkcji rozszerzenia można używać w dowolnym miejscu.

val imageView = findViewById(R.id.imageView)
imageView.setMarginExtensionFunction(0, 0, 0, 0)
enyciaa
źródło
1
działa to dla marginesów lefti right, ale jeśli masz marginesy względne ( starti end), to nie działa. Napisałem streszczenie z „ulepszoną” wersją Twojego kodu: gist.github.com/Grohden/f40c53bf86c5395638f7a44bf90e732d ( setMarginsRelativefunkcja) - czy możesz uwzględnić to w swojej odpowiedzi?
Gabriel De Oliveira Rohden
4

utwórz układ dynamicznie i ustaw jego parametr jako setmargin () nie będzie działać bezpośrednio na imageView

ImageView im;
im = (ImageView) findViewById(R.id.your_image_in_XML_by_id);
 RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(im.getLayoutParams());
                        layout.setMargins(counter*27, 0, 0, 0);//left,right,top,bottom
                        im.setLayoutParams(layout);
                        im.setImageResource(R.drawable.yourimage)
Muhammad Adil
źródło
4

U mnie to zadziałało:

int imgCarMarginRightPx = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, definedValueInDp, res.getDisplayMetrics());

MarginLayoutParams lp = (MarginLayoutParams) imgCar.getLayoutParams();
lp.setMargins(0,0,imgCarMarginRightPx,0);
imgCar.setLayoutParams(lp);
Wahib Ul Haq
źródło
2

przykładowy kod jest tutaj, jest bardzo łatwy

LayoutParams params1 = (LayoutParams)twoLetter.getLayoutParams();//twoletter-imageview
                params1.height = 70;
                params1.setMargins(0, 210, 0, 0);//top margin -210 here
                twoLetter.setLayoutParams(params1);//setting layout params
                twoLetter.setImageResource(R.drawable.oo);
Sydroid
źródło
0

Użycie metody podobnej do tej może w niektórych sytuacjach oszczędzić Ci bólu głowy. Jeśli masz dwa przebiegi programowego majstrowania przy marginesach, bezpieczniej jest sprawdzić, czy są już ustawione parametry layoutParams. Jeśli są już jakieś marże, to należy je zwiększyć, a nie zastępować:

public void addMargins(View v, int left, int top, int right, int bottom) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
    if (params == null)
        params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                               ViewGroup.LayoutParams.WRAP_CONTENT);
    int oldLeft = params.leftMargin;
    int oldTop = params.topMargin;
    int oldRight = params.rightMargin;
    int oldBottom = params.bottomMargin;
    params.setMargins(oldLeft + left, oldTop + top, oldRight + right, oldBottom + bottom);
    v.setLayoutParams(params);
}
GA1
źródło
0

Oto przykład dodania marginesu 8px po lewej, górnej, prawej i dolnej stronie.


ImageView imageView = new ImageView(getApplicationContext());

ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(
    ViewGroup.MarginLayoutParams.MATCH_PARENT,
    ViewGroup.MarginLayoutParams.WRAP_CONTENT
);

marginLayoutParams.setMargins(8, 8, 8, 8);

imageView.setLayoutParams(marginLayoutParams);
Md. Zubaer Ahammed
źródło
0

Odpowiedź z 2020 roku:

dependencies {
    implementation "androidx.core:core-ktx:1.2.0"
}

i wywołaj go po prostu w swoim kodzie

view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
   setMargins(5)
}
i30mb1
źródło