ใน Android ฉันจะตั้งค่าระยะขอบเป็น dp โดยทางโปรแกรมได้อย่างไร


401

ในนี้ , นี้และนี้ด้ายฉันพยายามที่จะหาคำตอบเกี่ยวกับวิธีการตั้งค่าระยะขอบบนมุมมองเดียว อย่างไรก็ตามฉันสงสัยว่าถ้าไม่มีวิธีที่ง่ายกว่านี้ ฉันจะอธิบายว่าทำไมฉันจึงไม่ต้องการใช้วิธีนี้:

ฉันมีปุ่มที่กำหนดเองซึ่งขยายปุ่ม หากพื้นหลังถูกตั้งค่าเป็นอย่างอื่นนอกเหนือจากพื้นหลังเริ่มต้น (โดยการเรียกอย่างใดอย่างหนึ่ง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ชั้นเรียนผู้ปกครองอาจแตกต่างจาก LinearLayout ถึง TableLayout และฉันไม่อยากให้เขาได้รับผู้ปกครองของเขาและตรวจสอบตัวอย่างของผู้ปกครองนั้น นั่นจะเป็นสิ่งที่ไม่มีประสิทธิภาพเลยทีเดียว

นอกจากนี้เมื่อโทร (โดยใช้ LayoutParams) parentLayout.addView(myCustomButton, newParams)ฉันไม่รู้ว่าสิ่งนี้เพิ่มเข้าไปในตำแหน่งที่ถูกต้อง (ยังไม่ได้ลอง) ให้พูดปุ่มกลางของแถวที่ห้า

คำถาม: มีวิธีใดที่ง่ายกว่าในการตั้งค่าระยะขอบของปุ่มเดียวโดยทางโปรแกรมนอกเหนือจากการใช้ 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) และ (oml, omr, omt, omb) และระยะขอบดั้งเดิม (ml, mr, mt, mb)

คำตอบ:


797

คุณควรใช้LayoutParamsเพื่อกำหนดระยะขอบปุ่มของคุณ:

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

ทั้งนี้ขึ้นอยู่กับสิ่งที่รูปแบบที่คุณกำลังใช้คุณควรใช้หรือRelativeLayout.LayoutParamsLinearLayout.LayoutParams

และหากต้องการแปลงการวัด dp ของคุณเป็นพิกเซลให้ลองสิ่งนี้:

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

152
ฉันควรนำเข้า LayoutParams ใดจากแพ็คเกจใด
stealthjong

7
setMargins ใช้ px และคุณจะใช้ dp, การแปลงของฉันถูกต้อง: dp -> px เพื่อตั้งค่าระยะขอบที่ถูกต้อง
throrin19


15
มันขึ้นอยู่กับเค้าโครงปัจจุบันของคุณ หากคุณอยู่ใน LinearLayout ให้ใช้ LinearLayout.LayoutParams RelativeLayout.LayoutParams เป็นอย่างอื่น
throrin19 19

5
คุณควรนำเข้า layoutParams ที่เป็นเลย์เอาต์หลักของคุณ <linearlayout> <relativelayout> <gridlayout> และคุณกำลังทำงานกับเค้าโครงตาราง จากนั้นคุณจะต้องใช้ relativelayout.layoutparams
Sruit A.Suk

228

LayoutParams - ไม่ทำงาน! ! !

ต้องการใช้ประเภท: MarginLayoutParams

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

ตัวอย่างรหัสสำหรับ MarginLayoutParams:

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


19
ถูกต้อง แต่ไม่จำเป็นต้องตั้งค่ากลับพารามิเตอร์ที่เปลี่ยนแปลงจะแสดงโดยอัตโนมัติ ดังนั้นคุณสามารถลบบรรทัด: vector8.setLayoutParams (params);
Wirsing

LayaoutParams มักสร้างความสับสนในขณะที่ตั้งค่าระยะขอบ ... ดังนั้น MarginLayoutParams นี้จึงมีประโยชน์มาก ขอบคุณ
Atul Bhardwaj

4
คุณจำเป็นต้องตั้งค่า LayoutParams (params) หลังจากการเปลี่ยนแปลงส่วนต่าง
Leo Droidcoder

ฉันพบ MarginLayoutParams เป็นคลาสใหม่วันนี้ # ขอบคุณ
Tushar Pandey

ใช้งานไม่ได้สำหรับButtonมุมมอง: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()ส่งคืนnull
Konstantin Konopko

118

วิธีที่ดีที่สุดที่เคย:

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

หวังว่านี่จะช่วยคุณได้


1
ฉันกำลังประสบปัญหาเมื่อฉันตั้งค่า setMargins (holder.vCenter, 0, 20, 0,0); เช่นนี้ขอบด้านซ้ายของมันทั้งสองด้าน (บนและล่าง) เกิดอะไรขึ้นกับ params ด้านบน
Arbaz.in

1
คำตอบที่สมบูรณ์แบบสุดยอดเยี่ยม !! ขอบคุณ!!
Sjd

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

15

นี่คือคำตอบแบบ all-in-one พร้อมอัปเดตล่าสุด:

ขั้นตอนที่ 1 เพื่ออัปเดตมาร์จิ้น

แนวคิดพื้นฐานคือการรับมาร์จิ้นแล้วอัปเดต การอัปเดตจะมีผลโดยอัตโนมัติและคุณไม่จำเป็นต้องตั้งค่ากลับ หากต้องการรับพารามิเตอร์โครงร่างเพียงเรียกเมธอดนี้:

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

LayoutParamsมาจากรูปแบบของมุมมองของคุณ LinearLayout.LayoutParamsถ้าดูจากรูปแบบเชิงเส้นที่คุณจำเป็นต้องนำเข้า หากคุณใช้เลย์เอาต์ที่สัมพันธ์กันการนำเข้าLinearLayout.LayoutParamsฯลฯ

ตอนนี้ถ้าคุณตั้งค่าขอบใช้Layout_marginLeft, Rightฯลฯ คุณจะต้องปรับปรุงอัตรากำไรในลักษณะนี้

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;

ตอนนี้ใส่ค่าที่คำนวณได้ไปยังฟังก์ชั่นการอัพเดทมาร์จิ้นข้างต้นและคุณควรจะตั้งค่าทั้งหมด


9

layout_margin เป็นข้อ จำกัด ที่เด็กดูบอกกับผู้ปกครอง อย่างไรก็ตามมันเป็นหน้าที่ของผู้ปกครองที่จะเลือกว่าจะอนุญาตหรือไม่ โดยพื้นฐานแล้วโดยการตั้งค่า android: layout_margin = "10dp" เด็ก ๆ จะวิงวอนกลุ่มมุมมองพาเรนต์เพื่อจัดสรรพื้นที่ที่10dp ใหญ่กว่าขนาดจริง (padding = "10dp" ในทางกลับกันหมายความว่ามุมมองลูกจะทำให้เนื้อหาของตัวเองเล็กลง 10dp )

ด้วยเหตุนี้อัตรากำไรของ ViewGroupsจึงไม่ได้ให้ความสำคัญ ตัวอย่างที่ฉาวโฉ่ที่สุดคือ listview โดยที่ระยะขอบของรายการจะถูกละเว้น ก่อนที่คุณจะเรียกsetMargin()ใช้ LayoutParam คุณควรตรวจสอบให้แน่ใจเสมอว่ามุมมองปัจจุบันอยู่ใน ViewGroup ที่รองรับระยะขอบ (เช่น LinearLayouot หรือ RelativeLayout) และส่งผลลัพธ์ของ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);
}

9

วิธีนี้จะช่วยให้คุณตั้งค่าระยะขอบใน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);
}

UPDATE

คุณสามารถเปลี่ยนพารามิเตอร์ที่เหมาะสมกับความต้องการของคุณ


8

ใน Kotlin จะมีลักษณะเช่นนี้:

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

3

เมื่อคุณอยู่ในมุมมองที่กำหนดเองคุณสามารถใช้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);
    }
}

1

ใช้วิธีนี้เพื่อตั้งค่าระยะขอบเป็น 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);

1

สำหรับการตั้งค่าแบบบรรทัดเดียวอย่างรวดเร็ว

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

แต่จะเป็น carfull สำหรับการใช้งาน LayoutParams ผิดเพราะจะไม่มีifกรณีใด ๆ


1

สร้างฟังก์ชั่น Kotlin Extension สำหรับผู้ที่อาจพบว่ามีประโยชน์

ตรวจสอบให้แน่ใจว่าส่งเป็นพิกเซลไม่ใช่ dp Happy coding :)

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

1

ในตัวอย่างของฉันฉันกำลังเพิ่ม ImageView ให้กับ LinearLayout โดยทางโปรแกรม ฉันตั้งระยะขอบด้านบนและล่างไว้ที่ ImagerView จากนั้นเพิ่ม ImageView ให้กับ LinearLayout



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

1

คุณสามารถใช้วิธีนี้และวางแบบคงที่หรี่เหมือน 20 มันแปลงตามอุปกรณ์ของคุณ

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

0

วันนี้สิ่งที่ดีที่สุดน่าจะเป็นปารีสซึ่งเป็นห้องสมุดของ AirBnB

สามารถใช้สไตล์ได้ดังนี้:

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

นอกจากนี้ยังสนับสนุนมุมมองที่กำหนดเอง (หากคุณขยายมุมมอง) โดยใช้คำอธิบายประกอบ:

@Styleable and @Style

0

คุณต้องโทร

setPadding(int left, int top, int right, int bottom)

ชอบมาก: your_view.setPadding(0,16,0,0)

สิ่งที่คุณพยายามใช้เป็นเพียงผู้ทะเยอทะยาน

Android studio แสดงให้เห็นpadding...()ถึงความหมายใน java:

ตัวอย่างการขยาย ภาพจะแสดงเฉพาะการโทรเท่านั้นgetPadding...()

หากคุณต้องการเพิ่มระยะขอบให้กับ 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

-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

ผมต้องทิ้งเราไปFrameLayoutหา LinearLayout ในขณะที่มันได้รับมรดกจากมันและอัตรากำไรขั้นต้นชุดมีดังนั้นกิจกรรมจะปรากฏเฉพาะในส่วนของหน้าจอพร้อมกับพื้นหลังที่แตกต่างจากรูปแบบเดิม params 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 ไม่เคยทำงานให้ฉัน - อุปกรณ์จะขัดข้องทุกครั้ง แม้ว่าจะเป็นหมายเลขฮาร์ดโค้ด - นี่เป็นเพียงตัวอย่างของรหัสสำหรับการสาธิตเท่านั้น


-1

คุณสามารถใช้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();ใช้ในค่าสำหรับซ้ายบนขวาล่างล่างตามลำดับ ตามเข็มนาฬิกา! เริ่มต้นจากทางซ้าย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.