在Android中,如何以编程方式在dp中设置边距?


401

这个这个这个线程中,我试图找到一个关于如何在单个视图上设置边距的答案。但是,我想知道是否没有更简单的方法。我将解释为什么我不想使用这种方法:

我有一个自定义按钮,它扩展了Button。如果背景设置为默认背景以外的其他值(通过调用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之外,还有其他任何更简便的方法以编程方式设置单个Button的边距吗?

编辑:我知道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,不具有的属性topMarginbottomMarginleftMarginrightMargin。您看到的mc实例只是一个MarginContainer包含偏移量(-3dp)边距和(oml,omr,omt,omb)和原始边距(ml,mr,mt,mb)的mc实例。

Answers:


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?
secretthjong 2012年

7
setMargins使用px,您将使用dp,我的转换是正确的:dp-> px设置正确的边距值。
throrin12年

6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln 2013年

15
这取决于您当前的布局。如果您位于LinearLayout中,请使用LinearLayout.LayoutParams。RelativeLayout.LayoutParams否则
throrin14年

5
您应该导入layoutParams,即您的父布局ex。<linearlayout> <relativelayout> <gridlayout>,您正在使用网格布局。然后,您需要使用relativelayout.layoutparams
Sruit A.Suk 2015年

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

LayaoutParams通常会在设置边距时造成混乱。因此,此MarginLayoutParams非常有用。谢谢
Atul Bhardwaj

4
您需要在边距更改后设置setLayoutParams(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)时遇到问题 像这样,它的左边距两侧(顶部和底部)上述参数有什么问题?
Arbaz.18年

1
很棒的完美答案!!谢谢!!
Sjd '19

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

这是最新更新的多合一答案:

步骤1,更新保证金

基本思想是获取保证金,然后进行更新。此更新将自动应用,您无需重新设置。要获取布局参数,只需调用此方法:

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

LayoutParams来自您的视图的布局。如果视图来自线性布局,则需要导入LinearLayout.LayoutParams。如果您使用相对布局,import LinearLayout.LayoutParams等。

现在,如果您使用Layout_marginLeftRight等设置边距,则需要以这种方式更新边距

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

如果使用new设置边距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。)

因此,并非所有ViewGroup都遵守margin。最臭名昭著的例子是列表视图,其中项目的边距被忽略。在调用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);
}

更新

您可以更改适合您需要的参数。


8

在Kotlin中,它将如下所示:

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

3

在自定义视图中时,可以使用getDimensionPixelSize(R.dimen.dimen_value),就我而言,我在init方法上创建的LayoutParams中添加了边距。

在科特林

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

但请认真对待LayoutParams的任何错误用法,因为这不会引起任何if陈述实例


1

为可能会方便使用的人创建了Kotlin扩展功能。

确保传递像素而不是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 }
            }
}

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,因为它继承自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从来没有为我工作-设备每次都会崩溃。即使这些是硬编码的数字-这仅是示例代码,仅用于演示目的。


-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();接受left,top,right,bottom的值。顺时针!,从左边开始。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.