在this,this和this主题中,我试图找到关于如何在单个视图上设置边距的答案。但是,我想知道是否有更简单的方法。我将解释为什么我宁愿不想使用这种方法:
我有一个扩展Button的自定义按钮。如果背景设置为默认背景以外的其他内容(通过调用setBackgroundResource(int id)
或setBackgroundDrawable(Drawable d)
),我希望边距为0.如果我这样称呼:
public void setBackgroundToDefault() {
backgroundIsDefault = true;
super.setBackgroundResource(android.R.drawable.btn_default);
// Set margins somehow
}
我希望边距重置为-3dp(我已经阅读了here如何从像素转换为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)。
答案 0 :(得分:686)
您应该使用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()
);
答案 1 :(得分:192)
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
答案 2 :(得分:98)
最佳方式:
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);
希望这会对你有所帮助。
答案 3 :(得分:28)
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);
答案 4 :(得分:7)
layout_margin是视图子项告诉其父级的约束。但是,父母的角色是选择是否允许保证金。基本上通过设置android:layout_margin =" 10dp",孩子正在恳求父视图组分配比实际大小 10dp更大的空间。 (padding =" 10dp",另一方面,意味着子视图将使自己的内容 10dp更小。)
因此,并非所有ViewGroup都尊重保证金。最臭名昭着的例子是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);
}
答案 5 :(得分:7)
此方法可让您在 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);
}
<强>更新强>
您可以更改符合您需要的参数。
答案 6 :(得分:2)
在自定义视图中时,可以使用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);
}
}
答案 7 :(得分:2)
独立设置所有/任意一侧:
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 }
答案 8 :(得分:2)
在Kotlin中,它将如下所示:
val layoutParams = (yourView?.layoutParams as? MarginLayoutParams)
layoutParams?.setMargins(40, 40, 40, 40)
yourView?.layoutParams = layoutParams
答案 9 :(得分:1)
使用单行快速设置
((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);
但是要认真对待LayoutParams的任何错误用法,因为这不会if
语句实例的出现
答案 10 :(得分:1)
使用 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();
}
}
答案 11 :(得分:1)
我在kotlin
中的工作方式
fun View.setTopMargin(@DimenRes dimensionResId: Int) {
(layoutParams as ViewGroup.MarginLayoutParams).topMargin = resources.getDimension(dimensionResId).toInt()
}
答案 12 :(得分:0)
使用 Android KTX,您可以执行以下操作:
yourView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
setMargins(0, 0, 0, 0)
}
答案 13 :(得分:0)
根据其他答案,我制作了一个通用扩展函数,它可以识别您的父级并相应地使用参数:
//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()
您也可以添加对其他父视图组的支持
答案 14 :(得分:0)
您必须致电
setPadding(int left, int top, int right, int bottom)
像这样:
your_view.setPadding(0,16,0,0)
您要使用的只是吸气剂。
Android Studio显示了padding...()
在Java中的实际含义:
padding example
该图像显示它仅调用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
答案 15 :(得分:0)
已更新:
就像您以前使用ViewGroup.LayoutParams
设置布局宽度和高度的方式一样
您可以使用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的值。从左开始顺时针!!
答案 16 :(得分:0)
您可以使用此方法,并放置20个静态维度,它会根据您的设备进行转换
public static int dpToPx(int dp)
{
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
答案 17 :(得分:0)
在我的示例中,我以编程方式将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);
答案 18 :(得分:0)
为可能会方便使用的人创建了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 }
}
}
答案 19 :(得分:0)
const uniques = [...new Set(myArray.filter(e => e))];
我必须将我的模型继承自linearLayout,并将其投放到((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
linearLayout.setBackgroundResource(R.drawable.smartlight_background);
上,并在此处设置边距,以便活动仅显示在屏幕的一部分上,并且背景与{{ 1}}。
FrameLayout
没有其他人使用相同的活动并通过从不同菜单打开活动来更改边距! setLayoutParams从来没有为我工作-设备每次都会崩溃。即使这些是硬编码的数字-这仅是示例代码,仅用于演示目的。
答案 20 :(得分:0)
使用此方法在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);
答案 21 :(得分:0)
就像今天一样,最好的方法是使用AirBnB提供的Paris库。
然后可以像这样应用样式:
Paris.style(myView).apply(R.style.MyStyle);
它还支持使用注释的自定义视图(如果您扩展视图):
@Styleable and @Style