Bir Görünümün Sağ Kenar Boşluğu Programlı Olarak Değiştirilsin mi?


173

Bu özellik Java kodunda dinamik olarak değiştirilebilir mi?

android:layout_marginRight

TextViewDinamik olarak sol bazı piksel konumunu değiştirmek zorunda bir , var.

Programlı olarak nasıl yapılır?

Yanıtlar:


463

DÜZENLEME: Düzen türüne bağlı olmayan (genel olarak kenar boşluklarını destekleyen bir düzen türü dışında) bunu yapmanın daha genel bir yolu:

public static void setMargins (View v, int l, int t, int r, int b) {
    if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
        ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
        p.setMargins(l, t, r, b);
        v.requestLayout();
    }
}

Dokümanları TextView için kontrol etmelisiniz . Temel olarak, TextView'in LayoutParams nesnesini almak ve kenar boşluklarını değiştirmek ve daha sonra tekrar TextView olarak ayarlamak istersiniz. Bir LinearLayout'ta olduğunu varsayarsak, böyle bir şey deneyin:

TextView tv = (TextView)findViewById(R.id.my_text_view);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)tv.getLayoutParams();
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
tv.setLayoutParams(params);

Şu anda test edemiyorum, bu yüzden dökümüm biraz kapalı olabilir, ancak LayoutParams kenar boşluğunu değiştirmek için değiştirilmesi gereken şeydir.

NOT

TextView'ünüz örneğin bir RelativeLayout içindeyse, LinearLayout.LayoutParams yerine RelativeLayout.LayoutParams kullanmanız gerektiğini unutmayın.


39
Başkalarının bunu araması durumunda cevabınızı ayrıntılı olarak açıklamak için. TextView programlı olarak oluşturuyorsanız, .getLayoutParams () aracılığıyla bir tane almaya çalışmak yerine, yeni bir LinearLayout.LayoutParams nesnesi de oluşturmanız gerekir.
Ares

Bu harika çalışıyor ve kenar boşluklarını piksel olarak ayarlıyor gibi görünüyor. Dp olarak ayarlamak mümkün mü?
SirRupertIII

3
@KKendall: Önce DP'nizi PX'e dönüştürün .
Kevin Coppock

NOTUNA göre: Şüphe duyuyorum. Metin görünümü veya düğme tablo satırının içindeyse? O zaman Göreli Düzen, Tablo Düzeni yerine ne kullanmalıyım?
tejas

1
Notla ilgili olarak, sadece tv.getLayoutParams () öğesini ViewGroup.MarginLayoutParams öğesine yayınlayabilirsiniz. Bu şekilde, marjları uyguladığı sürece hangi düzenin ayrıştırıcı olduğu önemli değildir
Radu Simionescu

17

LayoutParams kullanın (daha önce açıklandığı gibi). Ancak hangi LayoutParams'ı seçeceğinize dikkat edin. Göre https://stackoverflow.com/a/11971553/3184778 "Eğer üzerinde çalıştığınız bakış PARENT değil gerçek görünümü ile ilgilidir birini kullanmak gerekiyor"

Örneğin TextView bir TableRow içindeyse, RelativeLayout veya LinearLayout yerine TableRow.LayoutParams kullanmanız gerekir


Açıkladığınız için teşekkürler!
Scott Biggs

1
kenar boşluklarını ayarlamak için metin kutusu hedefini bilmeniz gerçekten berbat ... hedeften bağımsız bir çözüm olacağını düşünürdünüz.
TatiOverflow

10

Tüm kenar boşlukları türünü ayarlamak için Bu işlevi kullanın

      public void setViewMargins(Context con, ViewGroup.LayoutParams params,      
       int left, int top , int right, int bottom, View view) {

    final float scale = con.getResources().getDisplayMetrics().density;
    // convert the DP into pixel
    int pixel_left = (int) (left * scale + 0.5f);
    int pixel_top = (int) (top * scale + 0.5f);
    int pixel_right = (int) (right * scale + 0.5f);
    int pixel_bottom = (int) (bottom * scale + 0.5f);

    ViewGroup.MarginLayoutParams s = (ViewGroup.MarginLayoutParams) params;
    s.setMargins(pixel_left, pixel_top, pixel_right, pixel_bottom);

    view.setLayoutParams(params);
}

2
Neden ek 0.5f?
18'de

2
@behelit Bu geç olduğunu biliyorum ama arayan herkes için ... bir int için bir şamandıra, şamandıra yuvarlar. 0,0 -> 0,4 ​​mermi 0 iken 0,5 -> 0,9 mermi 1 olur. Bu, son girişlerde tutarsızlıklar oluşturabilir. Bunu önlemek için 0.5 ilavesi tüm yuvarlamanın 1 olmasını sağlar. Neden? şamandıranızın 1'e kadar yuvarlanan 0,3: 0,3 + 0,5 = 0,8 olduğunu söyleyin. Şamandıraınızın 1: 1'e aşağı yuvarlayan 0,8: 0,8 + 0,5 = 1,3 olduğunu söyleyin. negatif int almamak için çıkarma yerine 0.5 ekliyoruz)
Psest328 12:19

8

Güncelleme: Android KTX

Çekirdek ktx modülü Android çerçevenin bir parçası olan ortak kütüphaneler için uzantıları sağlar androidx.core.viewaralarında.

dependencies {
    implementation "androidx.core:core-ktx:{latest-version}"
}

Aşağıdaki uzantı işlevleri kenar boşluklarıyla başa çıkmak için kullanışlıdır:

İçinde Setleri tüm eksenlerin marjları ViewGroup's MarginLayoutParams. (Boyut piksel olarak sağlanmalıdır, dp ile çalışmak istiyorsanız son bölüme bakın)

inline fun MarginLayoutParams.setMargins(@Px size: Int): Unit
// E.g. 16px margins
val params = (myView.layoutParams as ViewGroup.MarginLayoutParams)
params.setMargins(16)

ViewGroup'S içindeki kenar boşluklarını günceller ViewGroup.MarginLayoutParams.

inline fun MarginLayoutParams.updateMargins(
    @Px left: Int = leftMargin, 
    @Px top: Int = topMargin, 
    @Px right: Int = rightMargin, 
    @Px bottom: Int = bottomMargin
): Unit
// Example: 8px left margin 
params.updateMargins(left = 8)

Güncellemeler göreli marjları ViewGroup'ın MarginLayoutParams(yerine sağ / sol başlat / son).

inline fun MarginLayoutParams.updateMarginsRelative(
    @Px start: Int = marginStart, 
    @Px top: Int = topMargin, 
    @Px end: Int = marginEnd, 
    @Px bottom: Int = bottomMargin
): Unit
// E.g: 8px start margin 
params.updateMargins(start = 8)

Aşağıdaki uzantı özellikleri, geçerli kenar boşluklarını elde etmek için kullanışlıdır:

inline val View.marginBottom: Int
inline val View.marginEnd: Int
inline val View.marginLeft: Int
inline val View.marginRight: Int
inline val View.marginStart: Int
inline val View.marginTop: Int
// E.g: get margin bottom
val bottomPx = myView1.marginBottom
  • Şunun dpyerine kullanma px:

dpBunun yerine (yoğunluktan bağımsız pikseller) ile çalışmak pxistiyorsanız, önce bunları dönüştürmeniz gerekir. Bunu aşağıdaki extension özelliği ile kolayca yapabilirsiniz:

val Int.px: Int
    get() = (this * Resources.getSystem().displayMetrics.density).toInt()

Sonra önceki uzantı işlevlerini çağırabilirsiniz:

params.updateMargins(start = 16.px, end = 16.px, top = 8.px, bottom = 8.px)
val bottomDp = myView1.marginBottom.dp

Eski cevap:

Kotlin'de aşağıdaki gibi bir uzantı işlevi bildirebilirsiniz:

fun View.setMargins(
    leftMarginDp: Int? = null,
    topMarginDp: Int? = null,
    rightMarginDp: Int? = null,
    bottomMarginDp: Int? = null
) {
    if (layoutParams is ViewGroup.MarginLayoutParams) {
        val params = layoutParams as ViewGroup.MarginLayoutParams
        leftMarginDp?.run { params.leftMargin = this.dpToPx(context) }
        topMarginDp?.run { params.topMargin = this.dpToPx(context) }
        rightMarginDp?.run { params.rightMargin = this.dpToPx(context) }
        bottomMarginDp?.run { params.bottomMargin = this.dpToPx(context) }
        requestLayout()
    }
}

fun Int.dpToPx(context: Context): Int {
    val metrics = context.resources.displayMetrics
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics).toInt()
}

Sonra şöyle diyebilirsiniz:

myView1.setMargins(8, 16, 34, 42)

Veya:

myView2.setMargins(topMarginDp = 8) 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.