Closed kirsysuv closed 8 years ago
Confirmed in a simpler layout without fragment. The layout is showed as below. The RecyclerView only have 1 item and the height is less than half of screen. When swipe upwards, the bottomnavigation will hide.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ky.swipelayouttest.MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</android.support.design.widget.CoordinatorLayout>
@kirsting It seems that the problem comes from the AHBottomNavigationBehavior class (or more precisely VerticalScrollingBehavior). I'm not sure I can do something from this class. What do you think?
I spend some time on it yesterday. I think the point is to use the dyConsumed to identify the scroll. dyConsumed will not be 0 when there is scrolling happening in other view. When dyConsumed is 0, which means there is no real scroll and the hide/show animation should not start. I tried to only response to onNestedScroll (this method give us dyConsumed) and it seems works. Below is the modified behavior which may not be the best implementation.
public class BottomNavigationBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {
private static final Interpolator INTERPOLATOR = new LinearOutSlowInInterpolator();
private static final int ANIM_DURATION = 300;
private static final int SCROLL_DIRECTION_DOWN = -1;
private static final int SCROLL_DIRECTION_UP = 1;
private int mTabLayoutId;
private boolean hidden = false;
private ViewPropertyAnimatorCompat translationAnimator;
private ObjectAnimator translationObjectAnimator;
private TabLayout mTabLayout;
private Snackbar.SnackbarLayout snackbarLayout;
private FloatingActionButton floatingActionButton;
private int mSnackbarHeight = -1;
private boolean fabBottomMarginInitialized = false;
private float targetOffset = 0, fabTargetOffset = 0, fabDefaultBottomMargin = 0, snackBarY = 0;
private boolean behaviorTranslationEnabled = true;
public BottomNavigationBehavior() {
super();
}
@Override
public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {
boolean layoutChild = super.onLayoutChild(parent, child, layoutDirection);
if (mTabLayout == null && mTabLayoutId != View.NO_ID) {
mTabLayout = findTabLayout(child);
}
return layoutChild;
}
private TabLayout findTabLayout(View child) {
if (mTabLayoutId == 0) return null;
return (TabLayout) child.findViewById(mTabLayoutId);
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
return super.onDependentViewChanged(parent, child, dependency);
}
@Override
public void onDependentViewRemoved(CoordinatorLayout parent, V child, View dependency) {
super.onDependentViewRemoved(parent, child, dependency);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
updateSnackbar(child, dependency);
updateFloatingActionButton(dependency);
return super.layoutDependsOn(parent, child, dependency);
}
//ViewCompat for Compatibility
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
//handleDirection based on dyConsumed
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed < 0) {
handleDirection(child, SCROLL_DIRECTION_DOWN);
} else if (dyConsumed > 0) {
handleDirection(child, SCROLL_DIRECTION_UP);
}
}
private void handleDirection(V child, int scrollDirection) {
if (scrollDirection == SCROLL_DIRECTION_DOWN && hidden) {
hidden = false;
animateOffset(child, 0, false, true);
} else if (scrollDirection == SCROLL_DIRECTION_UP && !hidden) {
hidden = true;
animateOffset(child, child.getHeight(), false, true);
}
}
...the rest is not modified
@kirsting Perfect, thanks, I'll add the fix on the next release (1.2.3).
Fixed in version 1.2.3
I have a RecyclerView inside SwipeLayout in a fragment. The navigation will always perform a hide animation when swipe up even there is not enough items in RecyclerView to scroll. The layout: