在这个,这个和这个线程中,我试图找到一个关于如何在单个视图上设置边缘的答案。然而,我想知道是否有更简单的方法。我将解释为什么我不想使用这种方法:
我有一个自定义按钮扩展按钮。如果背景被设置为默认背景以外的东西(通过调用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)。
当你在一个自定义视图中,你可以使用getDimensionPixelSize(r.d ine .dimen_value),在我的情况下,我在init方法上创建的LayoutParams中添加了边缘。
在Kotlin
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);
}
}
简单的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)
}
这也允许你做出水平或垂直的变化:
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)
}
注意:如果margin设置失败,你可能在渲染之前太早了,这意味着params == null。尝试用myView包装修改。Post {margin = 10}