프로그래밍 방식으로 뷰의 오른쪽 여백을 변경 하시겠습니까?


172

Java 코드에서이 속성을 동적으로 변경할 수 있습니까?

android:layout_marginRight

나는이 TextView, 그 일부 픽셀이 동적으로 왼쪽으로 위치를 변경한다.

프로그래밍 방식으로 수행하는 방법은 무엇입니까?

답변:


462

편집 : 레이아웃 유형에 의존하지 않는 일반적인 방법 (여백을 지원하는 레이아웃 유형 제외) :

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

TextView에 대한 문서를 확인해야합니다 . 기본적으로 TextView의 LayoutParams 객체를 가져오고 여백을 수정 한 다음 다시 TextView로 설정하려고합니다. 그것이 LinearLayout에 있다고 가정하면 다음과 같이 시도하십시오.

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

지금 테스트 할 수 없으므로 캐스팅이 약간 꺼져있을 수 있지만 LayoutParams는 여백을 변경하기 위해 수정해야합니다.

노트

당신의 텍스트 뷰 안에있는 경우, 예를 들어, 잊지 마세요 RelativeLayout의가 , 하나를 사용해야 RelativeLayout.LayoutParams을 LinearLayout.LayoutParams 대신


39
다른 사람들이 이것을 찾고있는 경우 답을 정교하게 작성하십시오. 프로그래밍 방식으로 TextView를 작성하는 경우 .getLayoutParams ()를 통해 오브젝트를 가져 오는 대신 새 LinearLayout.LayoutParams 오브젝트도 작성해야합니다.
Ares

이것은 훌륭하게 작동하며 여백을 픽셀 단위로 설정하는 것처럼 보입니다. dp로 설정할 수 있습니까?
SirRupertIII


귀하의 참고 사항에 따라 : 나는 의심합니다. 텍스트보기 또는 버튼이 테이블 행 안에 있다면? 그렇다면 상대 레이아웃, 테이블 레이아웃 대신 무엇을 사용해야합니까?
tejas

1
메모와 관련하여 tv.getLayoutParams ()를 ViewGroup.MarginLayoutParams로 캐스팅 할 수 있습니다. 이렇게하면 여백을 구현하는 한 패 런트가 어떤 레이아웃인지 중요하지 않습니다.
Radu Simionescu

17

이미 설명한대로 LayoutParams를 사용하십시오. 그러나 어떤 LayoutParam을 선택해야하는지주의하십시오. https://stackoverflow.com/a/11971553/3184778 에 따르면 "실제 뷰가 아니라 작업중인 뷰의 부모와 관련된 뷰를 사용해야합니다"

예를 들어 TextView가 TableRow 안에 있으면 RelativeLayout 또는 LinearLayout 대신 TableRow.LayoutParams를 사용해야합니다.


설명해 주셔서 감사합니다!
Scott Biggs

1
여백을 설정하려면 텍스트 상자 대상을 알아야한다는 사실이 정말 짜증납니다 ... 대상 독립적 인 솔루션이있을 것이라고 생각합니다.
TatiOverflow

10

이 기능을 사용하여 모든 여백 유형을 설정하십시오

      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
왜 추가 0.5f입니까?
behelit December

2
@behelit 나는 이것이 늦다는 것을 알고 있지만 찾고있는 사람이라면 ... float를 int로 캐스팅하면 float는 반올림됩니다. 0.0-> 0.4는 0으로 반올림되고 0.5-> 0.9는 1로 반올림됩니다. 이렇게하면 최종 정수에 불일치가 발생할 수 있습니다. 이를 방지하기 위해 0.5를 추가하면 모든 반올림이 1이됩니다. 왜 그렇습니까? 부동 소수점이 0.3 : 0.3 + 0.5 = 0.8이라고 말하면 최대 1로 반올림합니다. 부동 소수점이 0.8 : 0.8 + 0.5 = 1.3이면 DOWN을 1로 반올림합니다. 이제 최종 반올림에 대한 지식이 안전 할 수 있습니다 (측면 참고 : 음수 int를 피하기 위해 빼기보다는 0.5를 더합니다)
Psest328

7

업데이트 : Android KTX

코어 KTX 모듈은 안드로이드 프레임 워크의 일부 공통 라이브러리 확장을 제공한다 androidx.core.view그 (것)들의 사이에서.

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

다음 확장 기능은 여백을 처리하는 데 편리합니다.

에서 설정 모든 축의 여백을 ViewGroupMarginLayoutParams. (치수는 픽셀 단위로 제공해야합니다. dp로 작업하려면 마지막 섹션을 참조하십시오)

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

에서 업데이트 여백을 ViewGroupViewGroup.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)

갱신의 상대적인 마진 ViewGroupMarginLayoutParams(대신 왼쪽 / 오른쪽 시작 / 종료).

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)

다음 확장 속성은 현재 여백을 얻는 데 편리합니다.

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
  • dp대신에 사용 px:

작업 할 경우 dp대신 (밀도 독립적 픽셀) px먼저 변환해야합니다. 다음 확장 속성을 사용하면 쉽게 수행 할 수 있습니다.

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

그런 다음 다음과 같은 이전 확장 기능을 호출 할 수 있습니다.

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

이전 답변 :

Kotlin에서는 다음과 같은 확장 함수를 선언 할 수 있습니다.

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

그런 다음 다음과 같이 호출 할 수 있습니다.

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

또는:

myView2.setMargins(topMarginDp = 8) 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.