Material-components-android: [BottomNavigationView] Scrolling View offset for BottomNavigationView in CoordinatorLayout

Created on 16 Jul 2019  路  2Comments  路  Source: material-components/material-components-android

In CoordinatorLayout when I set a ScrollingViewBehavior for a RecyclerView it automatically creates an offset for AppBarLayout. But it doesn't create any offset for BottomNavigationView and BottomNavigationView overlaps the RecyclerView.

I can temporarily solve this problem by setting clipToPadding in RecyclerView. But BottomNavigationView also covers the over scroll animation.

feature request

Most helpful comment

I can temporarily solve this problem by setting clipToPadding in RecyclerView. But BottomNavigationView also covers the over scroll animation.

Hi @Sourav-21 , just faced the same problem yesterday and solved it by applying a custom scrolling behaviour to my recycler view. Here is the custom behaviour. Try if it may help you.

public class ScrollingViewAboveBottomNavigationBehavior extends AppBarLayout.ScrollingViewBehavior {

    private int marginBottom = 0;

    public ScrollingViewAboveBottomNavigationBehavior() {
        super();
    }

    public ScrollingViewAboveBottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return super.layoutDependsOn(parent, child, dependency)
                || (dependency instanceof BottomNavigationView);
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        return super.onDependentViewChanged(parent, child, dependency)
                | /* [!] single pipe is required */ updateBottomMarginIfNeeded(child, dependency);
    }

    private boolean updateBottomMarginIfNeeded(View child, View dependency) {
        if (dependency instanceof BottomNavigationView
                && dependency.getMeasuredHeight() != this.marginBottom) {
            this.marginBottom = dependency.getMeasuredHeight();
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            lp.bottomMargin = this.marginBottom;
            child.setLayoutParams(lp);
            return true;
        }
        return false;
    }
}

P.S. Perhaps, it's better to have this within the default behaviour, because it seems not so rare nowadays.

All 2 comments

I can temporarily solve this problem by setting clipToPadding in RecyclerView. But BottomNavigationView also covers the over scroll animation.

Hi @Sourav-21 , just faced the same problem yesterday and solved it by applying a custom scrolling behaviour to my recycler view. Here is the custom behaviour. Try if it may help you.

public class ScrollingViewAboveBottomNavigationBehavior extends AppBarLayout.ScrollingViewBehavior {

    private int marginBottom = 0;

    public ScrollingViewAboveBottomNavigationBehavior() {
        super();
    }

    public ScrollingViewAboveBottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return super.layoutDependsOn(parent, child, dependency)
                || (dependency instanceof BottomNavigationView);
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        return super.onDependentViewChanged(parent, child, dependency)
                | /* [!] single pipe is required */ updateBottomMarginIfNeeded(child, dependency);
    }

    private boolean updateBottomMarginIfNeeded(View child, View dependency) {
        if (dependency instanceof BottomNavigationView
                && dependency.getMeasuredHeight() != this.marginBottom) {
            this.marginBottom = dependency.getMeasuredHeight();
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            lp.bottomMargin = this.marginBottom;
            child.setLayoutParams(lp);
            return true;
        }
        return false;
    }
}

P.S. Perhaps, it's better to have this within the default behaviour, because it seems not so rare nowadays.

Thank you @dupovalo
It looks interesting. I shall try this. My new temporary solution is to put the whole CoordinatorLayout inside a LinearLayout.

Was this page helpful?
0 / 5 - 0 ratings