Thay đổi lề phải của chế độ xem theo chương trình?


172

Thuộc tính này có thể được thay đổi linh hoạt trong mã Java không?

android:layout_marginRight

Tôi có một TextView, mà phải thay đổi vị trí của nó một số pixel sang bên trái một cách linh hoạt.

Làm thế nào để làm điều đó theo chương trình?

Câu trả lời:


462

EDIT: Một cách chung hơn để làm điều này không phụ thuộc vào kiểu bố cục (khác với kiểu bố trí hỗ trợ lề):

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

Bạn nên kiểm tra các tài liệu cho TextView . Về cơ bản, bạn sẽ muốn lấy đối tượng LayoutParams của TextView và sửa đổi các lề, sau đó đặt nó trở lại TextView. Giả sử nó nằm trong linearLayout, hãy thử một cái gì đó như thế này:

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

Tôi không thể kiểm tra nó ngay bây giờ, do đó, quá trình truyền của tôi có thể bị tắt một chút, nhưng LayoutParams là thứ cần được sửa đổi để thay đổi lề.

GHI CHÚ

Đừng quên rằng nếu TextView của bạn ở bên trong, ví dụ, RelativeLayout , bạn nên sử dụng RelativeLayout.LayoutParams thay vì linearLayout.LayoutParams


39
Chỉ cần giải thích trong câu trả lời của bạn trong trường hợp người khác đang tìm kiếm điều này. Nếu bạn đang tạo TextView theo chương trình thì bạn cũng cần tạo một đối tượng linearLayout.LayoutParams mới, thay vì cố gắng lấy ra thông qua .getLayoutParams ();
Ares

Điều này hoạt động tuyệt vời, và có vẻ như nó đặt lề bằng pixel. Có thể đặt nó trong dp?
SirRupertIII

3
@KKendall: Chỉ cần chuyển đổi DP của bạn thành PX trước.
Kevin Coppock

Theo LƯU Ý của bạn: Tôi có nghi ngờ. Nếu textview hoặc một nút nằm trong một hàng của bảng? Vậy thì tôi nên sử dụng cái gì thay vì Relative Layout, Table Layout?
tejas

1
Liên quan đến ghi chú, bạn chỉ có thể truyền tv.getLayoutParams () sang Viewgroup.MarginLayoutParams. Bằng cách này, không có vấn đề gì về cách bố trí của parrent, miễn là nó thực hiện lề
Radu Simionescu

17

Sử dụng LayoutParams (như đã giải thích). Tuy nhiên, hãy cẩn thận khi chọn LayoutParams. Theo https://stackoverflow.com/a/11971553/3184778 "bạn cần sử dụng cái liên quan đến PHỤ HUYNH của chế độ xem bạn đang làm việc chứ không phải chế độ xem thực tế"

Ví dụ, nếu TextView nằm trong TableRow, thì bạn cần sử dụng TableRow.LayoutParams thay vì RelativeLayout hoặc linearLayout


Cảm ơn đã làm rõ!
Scott Biggie

1
nó thực sự hấp dẫn khi bạn phải biết đích của hộp văn bản để đặt lề ... bạn nghĩ rằng sẽ có một giải pháp là độc lập đích.
TatiOverflow

10

Sử dụng chức năng này để đặt tất cả các loại lề

      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
Tại sao thêm 0,5f?
xử

2
@behelit Tôi biết điều này là muộn nhưng đối với bất cứ ai đang tìm kiếm ... khi bạn thả một chiếc phao đến một int, các vòng tròn nổi. 0,0 -> 0,4 ​​vòng thành 0 trong khi 0,5 -> 0,9 vòng đến 1. Điều này có thể tạo ra sự không nhất quán trong các số nguyên cuối cùng. Để ngăn chặn điều này, thêm 0,5 đảm bảo tất cả làm tròn là 1. Tại sao? giả sử số float của bạn là 0,3: 0,3 + 0,5 = 0,8 làm tròn LÊN thành 1. Giả sử số float của bạn là 0,8: 0,8 + 0,5 = 1,3 mà làm tròn XUỐNG thành 1. Bây giờ bạn có thể an toàn trong kiến ​​thức của mình về cách làm tròn cuối cùng (LƯU Ý: chúng tôi cộng 0,5 thay vì trừ để tránh bị int âm)
Psest328

7

Cập nhật: Android KTX

Các mô-đun lõi KTX cung cấp phần mở rộng cho các thư viện phổ biến mà là một phần của khuôn khổ Android, androidx.core.viewtrong số đó.

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

Các chức năng mở rộng sau đây rất tiện để xử lý các lề:

Đặt lề của tất cả các trục trong ViewGroup's MarginLayoutParams. (Kích thước phải được cung cấp bằng pixel, xem phần cuối cùng nếu bạn muốn làm việc với dp)

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

Cập nhật lề trong ViewGroup's 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)

Cập nhật lề tương đối trong ViewGroup's MarginLayoutParams(bắt đầu / kết thúc thay vì trái / phải).

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)

Các thuộc tính mở rộng sau đây rất tiện lợi để có được tỷ suất lợi nhuận hiện tại:

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
  • Sử dụng dpthay vì px:

Nếu bạn muốn làm việc với dp(pixel độc lập với mật độ) thay vì px, bạn sẽ cần chuyển đổi chúng trước. Bạn có thể dễ dàng làm điều đó với thuộc tính mở rộng sau:

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

Sau đó, bạn có thể gọi các chức năng mở rộng trước đó như:

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

Câu trả lời cũ:

Trong Kotlin, bạn có thể khai báo một hàm mở rộng như:

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

Sau đó, bạn có thể gọi nó như:

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

Hoặc là:

myView2.setMargins(topMarginDp = 8) 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.