Changing fields inside a custom view

In my open source library FloatingActioButton I need to programmatically change the view fields set by the user. The margins should be reduced by the shadow size (so that the edge is set on the button, not on the shadow).

I override the onLayoutcustom view class and use the following code:

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

But when I test it on the example of the project, I see that the correct fields are applied only for the first time on the first fragment (ListView). When I click on another tab, a new fragment is created (a full layout is created) and the FAB is shifted (the fields do not decrease in size of the shadow):

Correct fields:

Correct margins

Invalid fields:

Wrong margins

, FAB . , , onLayout, . .

, onLayout ?

+4
1

, , 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;
        }
    }
}
+9

All Articles