sourcecode

안드로이드에서 프로그램적으로 dp에서 마진을 설정하려면 어떻게 해야 합니까?

codebag 2023. 6. 2. 20:28
반응형

안드로이드에서 프로그램적으로 dp에서 마진을 설정하려면 어떻게 해야 합니까?

스레드 스레드에서 저는 단일 뷰에서 여백을 설정하는 방법에 대한 답을 찾으려고 했습니다.하지만, 저는 더 쉬운 방법이 없는지 궁금합니다.이 접근 방식을 사용하고 싶지 않은 이유를 설명하겠습니다.

단추를 확장하는 사용자 지정 단추가 있습니다.이 아닌 ("" "" " " " " " " " " (" 중 하나를 으로써)setBackgroundResource(int id)또는setBackgroundDrawable(Drawable d)), 저는 마진이 0이 되기를 원합니다.내가 이걸 부르면,

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

여백을 -3dp로 재설정하고 싶습니다(픽셀에서 dp로 변환하는 방법을 이미 읽었기 때문에 px에서 여백을 설정하는 방법을 알게 되면 변환을 직접 관리할 수 있습니다).하지만 이것이 호출되었기 때문에.CustomButton클래스, 부모는 선형 레이아웃에서 테이블 레이아웃에 따라 다를 수 있으며, 저는 그가 부모를 데려와서 해당 부모의 인스턴스를 확인하지 않도록 하고 싶습니다.제 생각에는 그것도 꽤 비효율적일 것 같습니다.

(LayoutParams) 호출 (LayoutParams 사용)parentLayout.addView(myCustomButton, newParams)이것이 정확한 위치에 그것을 추가하는지 모르겠습니다. (그러나 시도하지 않았습니다.) 5열의 가운데 버튼을 말하세요.

질문:.LayoutParams를 사용하는 것 에 단일 버튼의 여백을 프로그래밍 방식으로 설정하는 더 쉬운 방법이 있습니까?

편집: LayoutParams 방법은 알고 있지만 각 컨테이너 유형을 처리하지 않는 솔루션을 원합니다.

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

ㅠㅠthis.getLayoutParams();를 반환합니다.ViewGroup.LayoutParams이 속이없것인 .topMargin,bottomMargin,leftMargin,rightMargin mc입니다.MarginContainer여기에는 오프셋(-3dp) 여백과 (omml, omr, ommt, omb) 및 원래 여백(ml, mr, mt, mb)이 포함됩니다.

당신은 야합다니해를 사용해야 .LayoutParams단추 여백을 설정하려면:

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

에 따라 해야 .RelativeLayout.LayoutParams또는LinearLayout.LayoutParams.

그리고 dp 측정값을 픽셀로 변환하려면 다음을 시도합니다.

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

레이아웃 매개 변수 - 작동하지 않습니다!

필요한 사용 유형: 여유 레이아웃 매개 변수

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

여백 레이아웃 매개변수의 코드 예:

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

최고의 방법:

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

메서드 호출 방법:

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

이것이 당신에게 도움이 되기를 바랍니다.

int sizeInDP = 16;

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

그리고나서

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

또는

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

Android KTX를 사용하면 다음과 같은 작업을 수행할 수 있습니다.

yourView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
   setMargins(0, 0, 0, 0)
}

다음은 최근 업데이트에 대한 올인원 답변입니다.

1단계, 마진 업데이트

기본 아이디어는 마진을 뺀 다음 업데이트하는 것입니다.업데이트가 자동으로 적용되므로 다시 설정할 필요가 없습니다.레이아웃 매개 변수를 가져오려면 다음 메서드를 호출합니다.

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

LayoutParams보기 레이아웃에서 가져옵니다.뷰가 선형 레이아웃에서 가져온 경우, 다음 항목을 가져와야 합니다.LinearLayout.LayoutParams레이아웃을 에는 상대레웃사경는우용하기, 오가져을아이를 가져옵니다.LinearLayout.LayoutParams 타기.

이 이다음사마설을 사용해서 하면,Layout_marginLeft,Rightetc,', .

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

사용하여 layout_marginStart.

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

2단계, dp 단위로 마진 업데이트

위의 마진을 업데이트하는 두 가지 방법은 모두 픽셀 단위로 업데이트됩니다.당신은 dp를 픽셀로 변환해야 합니다.

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

이제 위의 마진 업데이트 기능에 계산된 값을 입력하면 모든 설정이 완료됩니다.

코틀린에서는 다음과 같이 표시됩니다.

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

layout_module은 뷰 자식이 부모에게 알려주는 제약 조건입니다.하지만 마진을 허용할지 여부를 선택하는 것은 부모의 역할입니다.기본적으로 안드로이드:slid_dll="10dp"를 설정함으로써, 아이는 부모 뷰 그룹에 실제 크기보다 10dp 큰 공간을 할당해 달라고 간청합니다.(반면, "sigma="10dp"는 하위 보기가 자체 콘텐츠를 10dp 더 작게 만드는 것을 의미합니다.)

따라서 모든 보기 그룹이 마진을 존중하는 것은 아닙니다.가장 악명 높은 예는 항목의 여백이 무시되는 목록 보기입니다.전화하기 전에setMargin(), 하고 LayoutParam의 .getLayoutParams()원하는 특정 LayoutParams(레이아웃 파라미터)로 이동합니다.(ViewGroup.LayoutParams에는 조도없습다니도 없습니다.setMargins()방법!)

아래의 기능이 효과를 발휘해야 합니다.그러나 RelativeLayout을 상위 뷰 유형으로 대체해야 합니다.

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

방법을 사용하면 마진을 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);
}

갱신하다

필요에 따라 매개 변수를 변경할 수 있습니다.

당신은 이 방법을 사용하고 당신의 장치에 따라 변환되는 20개의 정적 치수를 넣을 수 있습니다.

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

간단한 Kotlin 확장 솔루션

모든/모든 면을 독립적으로 설정:

fun View.setMargin(left: Int? = null, top: Int? = null, right: Int? = null, bottom: Int? = null) {
    val params = (layoutParams as? MarginLayoutParams)
    params?.setMargins(
            left ?: params.leftMargin,
            top ?: params.topMargin,
            right ?: params.rightMargin,
            bottom ?: params.bottomMargin)
    layoutParams = params
}

myView.setMargin(10, 5, 10, 5)
// or just any subset
myView.setMargin(right = 10, bottom = 5)

리소스 값을 직접 참조합니다.

fun View.setMarginRes(@DimenRes left: Int? = null, @DimenRes top: Int? = null, @DimenRes right: Int? = null, @DimenRes bottom: Int? = null) {
    setMargin(
            if (left == null) null else resources.getDimensionPixelSize(left),
            if (top == null) null else resources.getDimensionPixelSize(top),
            if (right == null) null else resources.getDimensionPixelSize(right),
            if (bottom == null) null else resources.getDimensionPixelSize(bottom),
    )
}

myView.setMarginRes(top = R.dimen.my_margin_res)

모든 면을 속성으로 동일하게 직접 설정하려면:

var View.margin: Int
    get() = throw UnsupportedOperationException("No getter for property")
    set(@Px margin) = setMargin(margin, margin, margin, margin)
   
myView.margin = 10 // px

// or as res
var View.marginRes: Int
    get() = throw UnsupportedOperationException("No getter for property")
    set(@DimenRes marginRes) {
        margin = resources.getDimensionPixelSize(marginRes)
    }

myView.marginRes = R.dimen.my_margin_res

특정 면을 직접 설정하려면 다음과 같은 특성 확장을 작성할 수 있습니다.

var View.leftMargin
    get() = marginLeft
    set(@Px leftMargin) = setMargin(left = leftMargin)

var View.leftMarginRes: Int
    get() = throw UnsupportedOperationException("No getter for property")
    set(@DimenRes leftMarginRes) {
        leftMargin = resources.getDimensionPixelSize(leftMarginRes)
    }

이것은 당신이 만들 수 있게 해줍니다.horizontal또는vertical변형도 포함됩니다.

var View.horizontalMargin
    get() = throw UnsupportedOperationException("No getter for property")
    set(@Px horizontalMargin) = setMargin(left = horizontalMargin, right = horizontalMargin)

var View.horizontalMarginRes: Int
    get() = throw UnsupportedOperationException("No getter for property")
    set(@DimenRes horizontalMarginRes) {
        horizontalMargin = resources.getDimensionPixelSize(horizontalMarginRes)
    }

되지 않은 전에 할 수 . 즉, " ": 마진설에실경렌패전우더너에즉빨수수다행있리할습니무고참링"params == null수정 내용을 다음으로 포장해 보십시오.myView.post{ margin = 10 }

그것이 내가 해온 방법입니다.kotlin

fun View.setTopMargin(@DimenRes dimensionResId: Int) {
    (layoutParams as ViewGroup.MarginLayoutParams).topMargin = resources.getDimension(dimensionResId).toInt()
}

TextView에 여백을 추가하려면 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

레이아웃 매개변수는 상대, 선형, 보기 또는 보기 그룹과 같은 레이아웃일 수 있습니다.필요에 따라 LayoutParams(레이아웃 파라미터)를 선택합니다.감사해요.

Kotlin과 함께 사용할 수 있습니다.View.updateLayoutParams확장 기능:

yourView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
    setMargins(15,15,15,15)
}

// or

yourView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
    topMargin = 15
}

이 방법을 사용하여 마진(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();
    }
}

메서드 호출:

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

사용자 정의 보기에서 다음을 사용할 수 있습니다.getDimensionPixelSize(R.dimen.dimen_value)저의 경우, 저는 LayoutParams에 여백을 추가했습니다.init방법.

인 코틀린

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

Java:

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

빠른 한 줄 설정을 위해 사용

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

하십시오. 에는 " " " "라는 단어가 때문입니다. 이 경우에는 사용할 수 없습니다.ifstatement instance 인스턴스 체흐)

Kotlin Extension 기능은 유용할 수 있는 사람들을 위해 만들었습니다.

dp가 아닌 픽셀을 전달해야 합니다.해피 코딩 :)

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

이 예에서는 선형 레이아웃에 ImageView를 프로그래밍 방식으로 추가하고 있습니다.이미저 보기에 위쪽 및 아래쪽 여백을 설정했습니다.그런 다음 이미지 보기를 선형 레이아웃에 추가합니다.



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

작업 유틸리티는 관심 있는 사용자를 위해 DP를 사용하여 작동합니다.

public static void setMargins(Context context, View view, int left, int top, int right, int bottom) {
    int marginLeft = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, left, context.getResources().getDisplayMetrics());
    int marginTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, top, context.getResources().getDisplayMetrics());
    int marginRight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, right, context.getResources().getDisplayMetrics());
    int marginBottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, bottom, context.getResources().getDisplayMetrics());

    if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
        ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        p.setMargins(marginLeft, marginTop, marginRight, marginBottom);
        view.requestLayout();
    }
}

다른 답변을 바탕으로 부모님을 식별하고 그에 따라 매개변수를 사용하는 일반 확장 기능을 만들었습니다.

//takes margin values as integer , eg for 12dp top , you will pass 12
fun View?.setMarginFromConstant(mLeft:Int, mTop:Int, mRight:Int, mBottom:Int){
    this?.apply {
        val left = context?.dpToPixel(mLeft)?:0
        val top = context?.dpToPixel(mTop)?:0
        val right = context?.dpToPixel(mRight)?:0
        val bottom = context?.dpToPixel(mBottom)?:0
        when (val params = this.layoutParams) {
            is ConstraintLayout.LayoutParams -> {
                params.marginStart = left
                params.marginEnd = right
                params.topMargin = top
                params.bottomMargin = bottom
            }
            is FrameLayout.LayoutParams -> {
                params.marginStart = left
                params.marginEnd = right
                params.topMargin = top
                params.bottomMargin = bottom
            }
            is RecyclerView.LayoutParams -> {
                params.marginStart = left
                params.marginEnd = right
                params.topMargin = top
                params.bottomMargin = bottom
            }
        }
    }

}

그리고.

fun Context.dpToPixel(dp: Int): Int =
    (dp * applicationContext.resources.displayMetrics.density).toInt()

다른 상위 뷰 그룹에 대한 지원도 추가할 수 있습니다.

이 방법을 사용하여 dp를 올바르게 설정할 수 있습니다.

public int dpFormat(int dp) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

그리고 나서 전화합니다.

setMargins(dpFormat(15), dpFormat(15), dpFormat(15), dpFormat(15));
val params = FrameLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT,
    ViewGroup.LayoutParams.MATCH_PARENT
)
params.setMargins(0, 0, 0, 400)
binding.container.setLayoutParams(params)

@Lyusten Elder의 답은 맞지만, 하기 전에 px를 dp로 변환해야 한다는 것을 잊지 마세요.

다음과 같이:

public static int getDpFromPx(Context context, float px) {
    return Math.round(px * context.getResources().getDisplayMetrics().density);
}

현재로서는 에어비앤비에서 제공하는 도서관인 파리를 이용하는 것이 최선일 것입니다.

그런 다음 스타일을 다음과 같이 적용할 수 있습니다.

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

또한 주석을 사용하여 사용자 정의 보기(보기를 확장하는 경우)를 지원합니다.

@Styleable and @Style

저는 View Group을 사용하고 있었습니다.테마 단추 구성요소의 레이아웃 매개변수입니다.View Group을 사용합니다.레이아웃 매개 변수가 setMargin을 사용할 수 없습니다.

대신 아래와 같이 마진 레이아웃 매개변수를 사용하면 저에게 효과가 있었습니다.

ViewGroup.MarginLayoutParams params =new ViewGroup.MarginLayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        );
        params.setMargins(0,8,0,0);

저는 다음 코드가 작동했습니다.

buttonLinearLayout.layoutParams as MarginLayoutParams).apply 
{
   top.run { 
        topMargin = resources.getDimension(R.dimen.spacing).toInt() 
     }                        
}
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

나는 내 것을 던져야 했습니다.FrameLayout이 linearLayout의 .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);

다른 누구도 동일한 활동을 사용하고 다른 메뉴에서 활동을 여는 것을 기준으로 마진을 변경하지 않았습니다! setLayoutParams는 저를 위해 작동하지 않았습니다. 장치가 매번 충돌했습니다.하드 코딩된 숫자임에도 불구하고 이는 시연용 코드의 예에 불과합니다.

사용할 수 있습니다.ViewGroup.MarginLayoutParams, 하려면 " " " " " "을 선택합니다.

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

방법의 위치setMargins();왼쪽, 위쪽, 오른쪽, 아래쪽의 값을 각각 사용합니다.시계방향으로! 왼쪽부터 시작합니다.

언급URL : https://stackoverflow.com/questions/12728255/in-android-how-do-i-set-margins-in-dp-programmatically

반응형