How to sync scroll of two CoordinatorLayout + AppBarLayout - android

I have an activity with XML.
Something like:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/primary"
android:theme="#style/ToolbarStyle"
android:gravity="center_vertical"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways|snap"
style="#style/bold" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/TabLayoutStyle"
android:animateLayoutChanges="true"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabTextAppearance="#style/TabStyle"/>
</android.support.design.widget.AppBarLayout>
<com.wedmegood.planner.view.XViewPager
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
...
</android.support.v4.widget.DrawerLayout>
A Fragment of the ViewPager has a CoordinatorLayout and AppBarLayout + CollapsingToolbarLayout.
Fragment's XML:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/primaryDark"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapse_toolbar"
android:layout_width="match_parent"
android:layout_height="#dimen/my_wedding_banner_height"
android:minHeight="48dp"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<RelativeLayout
android:id="#+id/banner"
android:layout_width="match_parent"
android:layout_marginTop="0dp"
android:layout_height="match_parent"
app:layout_collapseMode="none">
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="bottom"
android:animateLayoutChanges="true"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabTextColor="#color/primary"
app:tabSelectedTextColor="#color/primary"
app:tabIndicatorColor="#color/accent"
app:tabIndicatorHeight="4dp"
app:tabTextAppearance="#style/TabStyle"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<com.wedmegood.planner.view.XViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
The fragment has a banner, the RelativeLayout. I want to sync scroll of these two AppBarLayouts so that the outer AppBar collapses either before/after (doesn't matter if it happens before or after) the inside AppBar collapses? I tried setting and unsetting scroll flags of 2 AppBars depending on their Offset change listener, it kinda works but doesn't give a smooth scroll effect. I can change the fragment's XML completely as long as the banner works fine.
Also, is there a way to change style / call TabLayout's setTabTextColors when CollapsingToolbarLayout collapses/expands?

I face the same problem days ago. Finally, I found a solution from SwipeRefreshLayout. Just extend CoordinatorLayout and implement NestedScrollingChild interface. It works!
here is my code:
public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild {
private final NestedScrollingChildHelper mNestedScrollingChildHelper;
private final int[] mParentOffsetInWindow = new int[2];
private final int[] mParentScrollConsumed = new int[2];
public NestedCoordinatorLayout(Context context) {
this(context, null, 0);
}
public NestedCoordinatorLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
// NestedScrollingChild
#Override
public void setNestedScrollingEnabled(boolean enabled) {
mNestedScrollingChildHelper.setNestedScrollingEnabled(enabled);
}
#Override
public boolean isNestedScrollingEnabled() {
return mNestedScrollingChildHelper.isNestedScrollingEnabled();
}
#Override
public boolean startNestedScroll(int axes) {
return mNestedScrollingChildHelper.startNestedScroll(axes);
}
#Override
public void stopNestedScroll() {
mNestedScrollingChildHelper.stopNestedScroll();
}
#Override
public boolean hasNestedScrollingParent() {
return mNestedScrollingChildHelper.hasNestedScrollingParent();
}
#Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
return mNestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, offsetInWindow);
}
#Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return mNestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
#Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return mNestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
#Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mNestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}
#Override
public void onNestedScrollAccepted(View child, View target, int axes) {
super.onNestedScrollAccepted(child, target, axes);
// Dispatch up to the nested parent
startNestedScroll(axes & ViewCompat.SCROLL_AXIS_VERTICAL);
}
#Override
public void onStopNestedScroll(View target) {
super.onStopNestedScroll(target);
stopNestedScroll();
}
#Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
mParentOffsetInWindow);
}
#Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(target, dx, dy, consumed);
final int[] parentConsumed = mParentScrollConsumed;
if (dispatchNestedPreScroll(dx - consumed[0], dy - consumed[1], parentConsumed, null)) {
consumed[0] += parentConsumed[0];
consumed[1] += parentConsumed[1];
}
}
}
Use it in your fragment's layout (Inner coordinator layout).

How can I sync scroll of these 2 AppBarLayouts so that the outer
appbar collapses either before/after (doesn't matter if it happens
before or after) the inside appbar collapses?
Delete that Fragment's CoordinatorLayout and just use RelativeLayout as a root tag (for Fragment)and then do your stuffs with that ViewPager in the MainActivity.
For example, use it inside that CoordinatorLayout like this:
<CoordinatorLayout>
<android.support.v4.view.ViewPager/>
<AppbarLayout/>
<scrollableView/>
<FloatingActionButton/>
</CoordinatorLayout>
Github example:
https://github.com/TheLittleNaruto/SupportDesignExample
Or perhaps you want to scroll that ViewPager inside the NestedScrollView but, you'll face a problem then use the following code inside it:
app:layout_behavior="#string/appbar_scrolling_view_behavior"
That's pretty much it.
A fragment of the ViewPager has a CoordinatorLayout and
AppBarLayout+CollapsingToolbarLayout. XML:
You don't need to use them twice.

Related

Nested CoordinatorLayout: Scroll not propagating to parent BottomNavigationView

My MainActivity contains my main content as a ViewPager2 as well as my BottomNavigationView, which has the hide_bottom_view_on_scroll_behavior. Each ViewPager2 child uses the appbar_scrolling_view_behavior and in most cases, this causes the bottom nav to hide when a child fragment is scrolled, which is the desired behavior.
However, on my child fragment that contains a CollapsingToolbarLayout with app:layout_scrollFlags="scroll", this behavior doesn't work. Removing the scrollFlags=scroll causes the bottom nav to act how it should. This leads me to believe that for some reason, the CollapsingToolbarLayout is intercepting the scroll behavior and it isn't propagating up to the bottom nav.
Any thoughts?
activity_main.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:nestedScrollingEnabled="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/main_bottom_navigation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp"
app:itemTextColor="?android:textColorPrimary"
android:layout_marginBottom="36dp"
app:itemIconTint="#color/nav_icon_tint"
android:background="#drawable/rounded_background"
app:backgroundTint="?android:colorPrimaryDark"
app:labelVisibilityMode="unlabeled"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:menu="#menu/activity_main_navigation"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
fragment_devotional.xml (child of ViewPager2)
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background"
android:theme="#style/AppTheme.AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="260dp"
android:fitsSystemWindows="true"
app:contentScrim="#color/background"
app:expandedTitleGravity="bottom"
app:expandedTitleTextAppearance="#style/Toolbar.ExpandedText"
app:layout_scrollFlags="scroll"
app:title="#{devotional.title}"
app:titleTextAppearance="#style/Toolbar.TitleText"
app:titleTextColor="?android:textColorPrimary"
app:toolbarId="#+id/toolbar">
<ImageView
android:id="#+id/header_logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:contentDescription="#{devotional.time}"
android:scaleType="center"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:textAlignment="textStart"
app:contentScrim="#color/background"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:title="#{devotional.title}" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
... content ....
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The problem is that you have a Coordinator Layout in another Coordinator Layout
the first CoordinatorLayout with the bottom Appbar doesnt get the scrolldata because the first one already consumes it.
what you need to do is to create a new type of Coordinator Layout that "communicates with the outer Coordinatorlayout (ie a nested Coordinator Layout).
public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild {
private NestedScrollingChildHelper mChildHelper;
public NestedCoordinatorLayout(Context context) {
super(context);
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
public NestedCoordinatorLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
#Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed, int type) {
int[][] tConsumed = new int[2][2];
super.onNestedPreScroll(target, dx, dy, consumed, type);
dispatchNestedPreScroll(dx, dy, tConsumed[1], null);
consumed[0] = tConsumed[0][0] + tConsumed[1][0];
consumed[1] = tConsumed[0][1] + tConsumed[1][1];
}
#Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
}
#Override
public void onStopNestedScroll(View target, int type) {
/* Disable the scrolling behavior of our own children */
super.onStopNestedScroll(target, type);
/* Disable the scrolling behavior of the parent's other children */
stopNestedScroll();
}
#Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes, int type) {
/* Enable the scrolling behavior of our own children */
boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes, type);
/* Enable the scrolling behavior of the parent's other children */
return startNestedScroll(nestedScrollAxes) || tHandled;
}
#Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
/* Enable the scrolling behavior of our own children */
boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes);
/* Enable the scrolling behavior of the parent's other children */
return startNestedScroll(nestedScrollAxes) || tHandled;
}
#Override
public void onStopNestedScroll(View target) {
/* Disable the scrolling behavior of our own children */
super.onStopNestedScroll(target);
/* Disable the scrolling behavior of the parent's other children */
stopNestedScroll();
}
#Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
int[][] tConsumed = new int[2][2];
super.onNestedPreScroll(target, dx, dy, tConsumed[0]);
dispatchNestedPreScroll(dx, dy, tConsumed[1], null);
consumed[0] = tConsumed[0][0] + tConsumed[1][0];
consumed[1] = tConsumed[0][1] + tConsumed[1][1];
}
#Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
}
#Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
boolean tHandled = super.onNestedPreFling(target, velocityX, velocityY);
return dispatchNestedPreFling(velocityX, velocityY) || tHandled;
}
#Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
boolean tHandled = super.onNestedFling(target, velocityX, velocityY, consumed);
return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled;
}
#Override
public boolean isNestedScrollingEnabled() {
return mChildHelper.isNestedScrollingEnabled();
}
#Override
public void setNestedScrollingEnabled(boolean enabled) {
mChildHelper.setNestedScrollingEnabled(enabled);
}
#Override
public boolean startNestedScroll(int axes) {
return mChildHelper.startNestedScroll(axes);
}
#Override
public void stopNestedScroll() {
mChildHelper.stopNestedScroll();
}
#Override
public boolean hasNestedScrollingParent() {
return mChildHelper.hasNestedScrollingParent();
}
#Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed, offsetInWindow);
}
#Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
#Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
#Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}}
use this for the inner coordinator layout and everything should work hopefully :)

BottomNavigationView not hide on scrollview

iam new to android,please help me.
i want to hide bottom navigation bar so i am using bottom navigation behavior,
i have a scrollview when i scroll the bottomnavigationbar scrolls, i dosent hide please help me
morethan a week am trying to solve this issue please help me
MainActivity.java
mBottomNavigationView=findViewById(R.id.bottom_nav);
mBottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_nav);
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mBottomNavigationView.getLayoutParams();
layoutParams.setBehavior(new BottomNavigationViewBehavior());
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.bottombaritem_map:
........
......
return true;
}
return false;
}
});
}
BottomNavigationViewBehavior
public class BottomNavigationViewBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {
private int height;
#Override
public boolean onLayoutChild(CoordinatorLayout parent, BottomNavigationView child, int layoutDirection) {
height = child.getHeight();
return super.onLayoutChild(parent, child, layoutDirection);
}
#Override
public boolean onStartNestedScroll(#NonNull CoordinatorLayout coordinatorLayout,
BottomNavigationView child, #NonNull
View directTargetChild, #NonNull View target,
int axes, int type)
{
return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
#Override
public void onNestedScroll(#NonNull CoordinatorLayout coordinatorLayout, #NonNull BottomNavigationView child,
#NonNull View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed,
#ViewCompat.NestedScrollType int type)
{
if (dyConsumed > 0) {
slideDown(child);
} else if (dyConsumed < 0) {
slideUp(child);
}
}
private void slideUp(BottomNavigationView child) {
child.clearAnimation();
child.animate().translationY(0).setDuration(200);
}
private void slideDown(BottomNavigationView child) {
child.clearAnimation();
child.animate().translationY(height).setDuration(200);
}
}
Layout xml file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_book_scrol1"
android:layout_width="fill_parent"
android:visibility="visible"
android:layout_height="fill_parent"
android:fillViewport="true">
...........
..........
</ScrollView>
<!---your RecyclerView/Fragment Container Layout-->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:itemBackground="#color/white"
app:menu="#menu/bottombar_menu" />
</android.support.design.widget.CoordinatorLayout>
<!---NavigationView-->
</android.support.v4.widget.DrawerLayout>

Show toolbar and bottom navigation view again

I have implemented show and hide functionality for toolbar and bottomNavigationView while scrolling up and down in recyclerView.
Now i click on recyclerView item and go to detail page which does not have recyclerView, now also toolbar and bottomNavigationView are hidden. Any method to make them visible again in this fragment.
main_activity.xml
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="5dp"
android:theme="#style/ToolbarTheme"
app:layout_scrollFlags="scroll|enterAlways"
app:titleTextAppearance="#style/Toolbar.TitleText" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
android:id="#+id/bottom_navigation_bar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
android:background="#drawable/menu_view"
android:isScrollContainer="false"
app:itemIconTint="#drawable/nav_item_color_state"
app:menu="#menu/my_navigation_items" />
BottomNavigationViewBehaviour.java
public class BottomNavigationViewBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {
private int height;
#Override
public boolean onLayoutChild(CoordinatorLayout parent, BottomNavigationView child, int layoutDirection) {
height = child.getHeight();
return super.onLayoutChild(parent, child, layoutDirection);
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child,
View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target,
int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if (dyConsumed > 0) {
slideDown(child);
} else if (dyConsumed < 0) {
slideUp(child);
}
}
private void slideUp(BottomNavigationView child) {
child.clearAnimation();
child.animate().translationY(0).setDuration(50);
}
private void slideDown(BottomNavigationView child) {
child.clearAnimation();
child.animate().translationY(height).setDuration(50);
}
}
MainActivity.java
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mBottomNav.getLayoutParams();
layoutParams.setBehavior(new BottomNavigationViewBehavior());
mBottomNav.clearAnimation();
mBottomNav.animate().translationY(mBottomNav.getHeight()).setDuration(100);
you can use AppbarLayout to expand using appbarLayout.setExpand(true) but this only show your action bar not your bottomNavigationbar.

How to hide Floating Action Button on Nested Scroll

I'm trying to hide two FAB on Nested Scroll scrolling. I've tried to implement my own FAB behavior but it did't work. FAB's don't react on scrolling at all. Note: I deleted some part of layout to fit the post.
Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="ru.berezin.maxim.im.budget_v3.userinterface.StartPage">
<android.support.design.widget.AppBarLayout
android:id="#+id/appcollapse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/testingscroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:behavior_overlapTop="30dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!--content including-->
<include layout="#layout/start_content_layout"/>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/start_page_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="#drawable/plus"
app:layout_anchor="#id/testingscroll"
app:layout_anchorGravity="end|bottom"
app:layout_behavior="ru.berezin.maxim.im.budget_v3.FabOnScroll"
/>
<View
android:id="#+id/dummy"
android:layout_width="1dp"
android:layout_height="16dp"
app:layout_anchor="#id/start_page_fab"
app:layout_anchorGravity="top|right|end"
/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/account_det_add_transfer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|top"
android:layout_margin="16dp"
android:src="#drawable/minus"
app:layout_anchor="#id/dummy"
app:layout_anchorGravity="top|right|end"
app:layout_behavior="ru.berezin.maxim.im.budget_v3.FabOnScroll"
/>
</android.support.design.widget.CoordinatorLayout>
FabOnScroll class
public class FabOnScroll extends FloatingActionButton.Behavior {
public FabOnScroll(Context context, AttributeSet attrs) {
super();
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
//child -> Floating Action Button
if (dyConsumed > 0) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
int fab_bottomMargin = layoutParams.bottomMargin;
child.animate().translationY(child.getHeight() + fab_bottomMargin).setInterpolator(new LinearInterpolator()).start();
} else if (dyConsumed < 0) {
child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
}
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}
So, I fixed it. Not exactly what I wanted, but it's working. I dont have any ideas why, but for some reason dyConsumed is always equals 0. But I noticed that dyUnconsumed is changing while I scroll. So I've just add dxUnconsumed check to my If/else statment and it's worked. Can someone explain why dyConsumed equals 0?
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if (dy > 0 ||dy<0 && fab.isShown())
{
fab.hide();
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
if (newState == RecyclerView.SCROLL_STATE_IDLE)
{
fab.show();
}
super.onScrollStateChanged(recyclerView, newState);
}
});
I know it's a late answer but my solution is to use dyUnconsumed instead of dyConsumed inside the if statement and it worked very well with me
if (dyUnconsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
#Override
public void onHidden(FloatingActionButton fab) {
super.onHidden(fab);
child.setVisibility(View.INVISIBLE);
}
});
} else if (dyUnconsumed <0 && child.getVisibility() != View.VISIBLE) {
child.show();
}

FloatingActionButton under CoordiantorLayout is not animating

I am trying to animate the FloatingActionButton (Under CoordiantorLayout).When a user scrolls down a page, the floating action button should disappear. Once the page scrolls to the top, it should reappear.However it's not working as i expected Where do I mess up?
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/DrawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:elevation="7dp"
tools:context=".MainActivity">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/tool_bar"
layout="#layout/tool_bar"></include>
<android.support.v7.widget.RecyclerView
android:id="#+id/tripslist"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/createfab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="#drawable/ic_plus"
app:backgroundTint="#color/colorPrimary"
app:layout_behavior="mogo.trasome.views.ScrollAwareFABBehavior" />
</android.support.design.widget.CoordinatorLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/RecyclerView"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#ffffff"
android:scrollbars="vertical" />
</android.support.v4.widget.DrawerLayout>
This is my Behavior class,
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (child.getVisibility() == View.VISIBLE && dyConsumed > 0) {
child.hide();
} else if (child.getVisibility() == View.GONE && dyConsumed < 0) {
child.show();
}
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}

Categories

Resources