更改自定义视图中的边距

时间:2014-12-04 15:07:52

标签: android android-layout layout

在我的开源库FloatingActioButton中,我需要以编程方式更改用户指定的视图边距。边距必须减少阴影大小(因此边距设置为按钮本身而不是阴影)。

我覆盖自定义视图类的onLayout并使用以下代码:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    if (!hasLollipopApi() && !mMarginsSet) {
        if (getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
            int leftMargin = lp.leftMargin - mShadowSize;
            int topMargin = lp.topMargin - mShadowSize;
            int rightMargin = lp.rightMargin - mShadowSize;
            int bottomMargin = lp.bottomMargin - mShadowSize;
            lp.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);

            setLayoutParams(lp);
            mMarginsSet = true;
        }
    }
}

但是当我在示例项目上测试它时,我发现只有第一次在第一个片段(ListView)上应用了正确的边距。当我单击另一个选项卡时,会创建一个新片段(因此创建完整的布局)并且FAB会移位(边距不会减少阴影大小):

更正边距:

Correct margins

错误的保证金:

Wrong margins

即使我返回第一个标签页,FAB也会保留错误的边距。我尝试调试并发现在onLayout中计算的值在所有情况下都是相同的。边距计算正确。

可能onLayout不是改变边距的正确位置?

1 个答案:

答案 0 :(得分:13)

我通过调用将边距设置为onMeasure方法来修复它:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int size = getDimension(
        mType == TYPE_NORMAL ? R.dimen.fab_size_normal : R.dimen.fab_size_mini);
    if (mShadow && !hasLollipopApi()) {
        size += mShadowSize * 2;
        setMarginsWithoutShadow();
    }
    setMeasuredDimension(size, size);
}

private void setMarginsWithoutShadow() {
    if (!mMarginsSet) {
        if (getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
            int leftMargin = layoutParams.leftMargin - mShadowSize;
            int topMargin = layoutParams.topMargin - mShadowSize;
            int rightMargin = layoutParams.rightMargin - mShadowSize;
            int bottomMargin = layoutParams.bottomMargin - mShadowSize;
            layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);

            requestLayout();
            mMarginsSet = true;
        }
    }
}