Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change margins inside a custom view

In my open source library FloatingActioButton I need to programmatically change view margins specified by a user. Margins must be reduced by a shadow size (so that margin is set to the button itself and not to the shadow).

I override the onLayout of the custom 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 sample project I see that correct margins are applied only the first time on the first fragment (ListView). When I click on another tab, a new fragment is created (so complete layout is created) and the FAB is shifted (margins are not reduced by the shadow size):

Correct margins:

Correct margins

Wrong margins:

Wrong margins

Even when I return to the first tab, the FAB stays with wrong margins. I tried to debug and saw that values calculated in onLayout are the same in all cases. Margins calculated correctly.

Maybe onLayout is not correct place to change margins?

like image 314
makovkastar Avatar asked Dec 04 '14 15:12

makovkastar


1 Answers

I fixed it by moving a call to set margins to the onMeasure method:

@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;
        }
    }
}
like image 107
makovkastar Avatar answered Oct 30 '22 20:10

makovkastar