Android RecyclerView 首条悬停 可加动画 coordi

Android RecyclerView 首条悬停 可加动画 coordi_第1张图片

 我是看的大佬的 Demo

https://me.csdn.net/qq_30447263

这个的应用场景很多,除了动画 自己需要摸索 就是这个Behavior延伸了


 

此处为动画

 appBarLayout.addOnOffsetChangedListener(new AppBarLayout.BaseOnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                //下降分度
                float fraction = -verticalOffset * 1.f / (mIdTvMoving.getHeight() - mIdTvMoving.getMinHeight());
                int color = ColUtils.evaluateColor(fraction, 0xffF07054, 0xff3F51B5);
                mIdTvMoving.setBackgroundColor(color);//颜色过渡
                mIdTvMoving.setTextSize(40 * (1 - fraction));//字号缩小
                mIdTvMoving.setTranslationX(-fraction * mIdTvMoving.getWidth());//X平移
            }
        });

 


 




    

        

        

        

        

    


    

    
    
    
    



public class ColUtils {
    /**
     * 改变一个颜色的透明度
     *
     * @param color
     * @param alpha
     */
    public static int changeColorAlpha(int color, int alpha) {
        int a = (color >> 24) & 0xFF;
        a = (int) (a * (alpha / 255f));
        int r = (color >> 16) & 0xFF;
        int g = (color >> 8) & 0xFF;
        int b = color & 0xFF;
        return (a << 24) | (r << 16) | (g << 8) | b;
    }

    /**
     * 返回随机颜色
     *
     * @return 随机颜色
     */
    public static int randomColor() {
        Random random = new Random();
        int a = 250 + random.nextInt(255);
        int r = 30 + random.nextInt(200);
        int g = 30 + random.nextInt(200);
        int b = 30 + random.nextInt(200);
        int randomColor = Color.argb(a, r, g, b);

        return randomColor;

    }

    /**
     * 返回随机颜色
     *
     * @return 随机颜色
     */
    public static int randomRGB() {
        Random random = new Random();
        int r = 30 + random.nextInt(200);
        int g = 30 + random.nextInt(200);
        int b = 30 + random.nextInt(200);
        return Color.rgb(r, g, b);
    }

    /**
     * 颜色变换
     *
     * @param fraction 分度值
     * @param startValue 开始色
     * @param endValue 结束色
     * @return 分度值处颜色
     */
    public static int evaluateColor(float fraction, int startValue,
                                       int endValue) {
        int startA = (startValue >> 24) & 0xff;
        int startR = (startValue >> 16) & 0xff;
        int startG = (startValue >> 8) & 0xff;
        int startB = startValue & 0xff;

        int endA = (endValue >> 24) & 0xff;
        int endR = (endValue >> 16) & 0xff;
        int endG = (endValue >> 8) & 0xff;
        int endB = endValue & 0xff;

        return (startA + (int) (fraction * (endA - startA)) << 24)
                | (startR + (int) (fraction * (endR - startR)) << 16)
                | (startG + (int) (fraction * (endG - startG)) << 8)
                | startB + (int) (fraction * (endB - startB));
    }

    private static final int ENABLE_ATTR = android.R.attr.state_enabled;
    private static final int CHECKED_ATTR = android.R.attr.state_checked;
    private static final int PRESSED_ATTR = android.R.attr.state_pressed;

    /**
     * @param tintColor
     * @return
     */
    public static ColorStateList generateThumbColorWithTintColor(final int tintColor) {
        int[][] states = new int[][]{
                {-ENABLE_ATTR, CHECKED_ATTR},
                {-ENABLE_ATTR},
                {PRESSED_ATTR, -CHECKED_ATTR},
                {PRESSED_ATTR, CHECKED_ATTR},
                {CHECKED_ATTR},
                {-CHECKED_ATTR}
        };

        int[] colors = new int[]{
                tintColor - 0xAA000000,
                0xFFBABABA,
                tintColor - 0x99000000,
                tintColor - 0x99000000,
                tintColor | 0xFF000000,
                0xFFEEEEEE
        };
        return new ColorStateList(states, colors);
    }

    /**
     * @param tintColor
     * @return
     */
    public static ColorStateList generateBackColorWithTintColor(final int tintColor) {
        int[][] states = new int[][]{
                {-ENABLE_ATTR, CHECKED_ATTR},
                {-ENABLE_ATTR},
                {CHECKED_ATTR, PRESSED_ATTR},
                {-CHECKED_ATTR, PRESSED_ATTR},
                {CHECKED_ATTR},
                {-CHECKED_ATTR}
        };

        int[] colors = new int[]{
                tintColor - 0xE1000000,
                0x10000000,
                tintColor - 0xD0000000,
                0x20000000,
                tintColor - 0xD0000000,
                0x20000000
        };
        return new ColorStateList(states, colors);
    }

    /**
     * 颜色加深处理
     *
     * @param RGBValues RGB的值,由alpha(透明度)、red(红)、green(绿)、blue(蓝)构成,
     *                  Android中我们一般使用它的16进制,
     *                  例如:"#FFAABBCC",最左边到最右每两个字母就是代表alpha(透明度)、
     *                  red(红)、green(绿)、blue(蓝)。每种颜色值占一个字节(8位),值域0~255
     *                  所以下面使用移位的方法可以得到每种颜色的值,然后每种颜色值减小一下,在合成RGB颜色,颜色就会看起来深一些了
     * @return
     */
    public static int colorBurn(int RGBValues) {
        int red = RGBValues >> 16 & 0xFF;
        int green = RGBValues >> 8 & 0xFF;
        int blue = RGBValues & 0xFF;
        red = (int) Math.floor(red * (1 - 0.1));
        green = (int) Math.floor(green * (1 - 0.1));
        blue = (int) Math.floor(blue * (1 - 0.1));
        return Color.rgb(red, green, blue);
    }
}

 可以设置 开始的颜色 --->  结束的颜色 


没多少代码 ~  几乎都是粘的 

然后是Behavior

这个效果可以应用在 底部导航栏 当然要求

 

 

Android RecyclerView 首条悬停 可加动画 coordi_第2张图片

 

这个效果写在一些小界面 可以 ,完全体的导航栏还是去=>>github

public abstract class VerticalScrollingBehavior extends CoordinatorLayout.Behavior {

    private int mTotalDyUnconsumed = 0;
    private int mTotalDyConsumed = 0;
    private int mTotalDy = 0;

    @ScrollDirection
    private int mScrollDirection = ScrollDirection.SCROLL_NONE;
    @ScrollDirection
    private int mPreScrollDirection = ScrollDirection.SCROLL_NONE;
    @ScrollDirection
    private int mConsumedScrollDirection = ScrollDirection.SCROLL_NONE;

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

    public VerticalScrollingBehavior() {
        super();
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ScrollDirection.SCROLL_DIRECTION_UP, ScrollDirection.SCROLL_DIRECTION_DOWN})
    public @interface ScrollDirection {
        int SCROLL_DIRECTION_UP = 1;
        int SCROLL_DIRECTION_DOWN = -1;
        int SCROLL_NONE = 0;
    }


    /**
     * @return Scroll direction: SCROLL_DIRECTION_UP, CROLL_DIRECTION_DOWN, SCROLL_NONE
     */
    @ScrollDirection
    public int getScrollDirection() {
        return mScrollDirection;
    }

    /**
     * @return ConsumedScroll direction: SCROLL_DIRECTION_UP, CROLL_DIRECTION_DOWN, SCROLL_NONE
     */
    @ScrollDirection
    public int getConsumedScrollDirection() {
        return mConsumedScrollDirection;
    }


    /**
     * @return PreScroll direction: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN, SCROLL_NONE
     */
    @ScrollDirection
    public int getPreScrollDirection() {
        return mPreScrollDirection;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
        return (nestedScrollAxes & View.SCROLL_AXIS_VERTICAL) != 0;
    }

//    @Override
//    public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
//        super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
//    }
//
//    @Override
//    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
//        super.onStopNestedScroll(coordinatorLayout, child, target);
//    }

    @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 (dyUnconsumed > 0 && mTotalDyUnconsumed < 0) {
            mTotalDyUnconsumed = 0;
            mScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP;
            onNestedVerticalScrollUnconsumed(coordinatorLayout, child, mScrollDirection, dyConsumed, mTotalDyUnconsumed);
        } else if (dyUnconsumed < 0 && mTotalDyUnconsumed > 0) {
            mTotalDyUnconsumed = 0;
            mScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN;
            onNestedVerticalScrollUnconsumed(coordinatorLayout, child, mScrollDirection, dyConsumed, mTotalDyUnconsumed);
        }
        mTotalDyUnconsumed += dyUnconsumed;

        if (dyConsumed > 0 && mTotalDyConsumed < 0) {
            mTotalDyConsumed = 0;
            mConsumedScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP;
            onNestedVerticalScrollConsumed(coordinatorLayout, child, mConsumedScrollDirection, dyConsumed, mTotalDyConsumed);
        } else if (dyConsumed < 0 && mTotalDyConsumed > 0) {
            mTotalDyConsumed = 0;
            mConsumedScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN;
            onNestedVerticalScrollConsumed(coordinatorLayout, child, mConsumedScrollDirection, dyConsumed, mTotalDyConsumed);
        }
        mTotalDyConsumed += dyConsumed;
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
        if (dy > 0 && mTotalDy < 0) {
            mTotalDy = 0;
            mPreScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP;
            onNestedVerticalPreScroll(coordinatorLayout, child, target, dx, dy, consumed, mPreScrollDirection);
        } else if (dy < 0 && mTotalDy > 0) {
            mTotalDy = 0;
            mPreScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN;
            onNestedVerticalPreScroll(coordinatorLayout, child, target, dx, dy, consumed, mPreScrollDirection);
        }
        mTotalDy += dy;
    }


    @Override
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed) {
        super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
        return onNestedDirectionFling(coordinatorLayout, child, target, velocityX, velocityY, consumed
                , velocityY > 0 ? ScrollDirection.SCROLL_DIRECTION_UP : ScrollDirection.SCROLL_DIRECTION_DOWN);
    }

    /**
     * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
     *                          associated with
     * @param child             the child view of the CoordinatorLayout this Behavior is associated with
     * @param scrollDirection   Direction of the scroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN
     * @param currentOverScroll Unconsumed value, negative or positive based on the direction;
     * @param totalScroll       Cumulative value for current direction (Unconsumed)
     */
    public abstract void onNestedVerticalScrollUnconsumed(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int scrollDirection, int currentOverScroll, int totalScroll);

    /**
     * @param coordinatorLayout   the CoordinatorLayout parent of the view this Behavior is
     *                            associated with
     * @param child               the child view of the CoordinatorLayout this Behavior is associated with
     * @param scrollDirection     Direction of the scroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN
     * @param currentOverScroll   Unconsumed value, negative or positive based on the direction;
     * @param totalConsumedScroll Cumulative value for current direction (Unconsumed)
     */
    public abstract void onNestedVerticalScrollConsumed(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int scrollDirection, int currentOverScroll, int totalConsumedScroll);

    /**
     * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
     *                          associated with
     * @param child             the child view of the CoordinatorLayout this Behavior is associated with
     * @param target            the descendant view of the CoordinatorLayout performing the nested scroll
     * @param dx                the raw horizontal number of pixels that the user attempted to scroll
     * @param dy                the raw vertical number of pixels that the user attempted to scroll
     * @param consumed          out parameter. consumed[0] should be set to the distance of dx that
     *                          was consumed, consumed[1] should be set to the distance of dy that
     *                          was consumed
     * @param scrollDirection   Direction of the scroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN
     */
    public abstract void onNestedVerticalPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection);

    /**
     * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
     *                          associated with
     * @param child             the child view of the CoordinatorLayout this Behavior is associated with
     * @param target            the descendant view of the CoordinatorLayout performing the nested scroll
     * @param velocityX         horizontal velocity of the attempted fling
     * @param velocityY         vertical velocity of the attempted fling
     * @param consumed          true if the nested child view consumed the fling
     * @param scrollDirection   Direction of the scroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN
     * @return true if the Behavior consumed the fling
     */
    protected abstract boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed, @ScrollDirection int scrollDirection);

//    @Override
//    public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
//        return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
//    }
//
//    @Override
//    public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, V child, WindowInsetsCompat insets) {
//
//        return super.onApplyWindowInsets(coordinatorLayout, child, insets);
//    }
//
//    @Override
//    public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) {
//        return super.onSaveInstanceState(parent, child);
//    }

}
public class BottomVerticalScrollBehavior extends VerticalScrollingBehavior {
    private static final Interpolator INTERPOLATOR = new LinearOutSlowInInterpolator();
    private int mBottomNavHeight;
    private int mDefaultOffset;
//    private WeakReference mViewRef;

    private ViewPropertyAnimatorCompat mTranslationAnimator;
    private boolean hidden = false;

    @Override
    public boolean onLayoutChild(CoordinatorLayout parent, final V child, int layoutDirection) {
        // First let the parent lay it out
        parent.onLayoutChild(child, layoutDirection);
//        mViewRef = new WeakReference<>(child);

        child.post(new Runnable() {
            @Override
            public void run() {
                mBottomNavHeight = child.getHeight();
            }
        });

        mDefaultOffset = 0;

        return super.onLayoutChild(parent, child, layoutDirection);
    }

    @Override
    public void onNestedVerticalScrollUnconsumed(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int scrollDirection, int currentOverScroll, int totalScroll) {
        // Empty body
    }

    @Override
    public void onNestedVerticalPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection) {
//        handleDirection(child, scrollDirection);
    }

    @Override
    public void onNestedVerticalScrollConsumed(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int scrollDirection, int currentOverScroll, int totalConsumedScroll) {
        handleDirection(child, scrollDirection);
    }

    private void handleDirection(V child, int scrollDirection) {
        if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_DOWN && hidden) {
            hidden = false;
            animateOffset(child, mDefaultOffset);
        } else if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_UP && !hidden) {
            hidden = true;
            animateOffset(child, mBottomNavHeight + mDefaultOffset);
        }
    }

    @Override
    protected boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed, @ScrollDirection int scrollDirection) {
        if (consumed) {
            handleDirection(child, scrollDirection);
        }
        return consumed;
    }

    private void animateOffset(final V child, final int offset) {
        ensureOrCancelAnimator(child);
        mTranslationAnimator.translationY(offset).start();
    }

    private void ensureOrCancelAnimator(V child) {
        if (mTranslationAnimator == null) {
            mTranslationAnimator = ViewCompat.animate(child);
            mTranslationAnimator.setDuration(400);
            mTranslationAnimator.setInterpolator(INTERPOLATOR);
        } else {
            mTranslationAnimator.cancel();
        }
    }
}
public class BnbFollowListBehavior extends BottomVerticalScrollBehavior {

    public BnbFollowListBehavior(Context context, AttributeSet attributeSet) {
        super();
    }
}





    

    
    
    
    


 


和上面一样效果 代码少了很多

public class FabFollowListBehavior extends CoordinatorLayout.Behavior {
    private static final int MIN_DY = 30;
    private static final String TAG = "FabFollowListBehavior";
 
    public FabFollowListBehavior(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }
 
    /**
     * 初始时不调用,滑动时调用---一次滑动过程,之调用一次
     */
    @Override
    public boolean onStartNestedScroll(
            @NonNull CoordinatorLayout coordinatorLayout,
            @NonNull FloatingActionButton child,
            @NonNull View directTargetChild,
            @NonNull View target, int axes, int type) {
        return true;
    }
 
    /**
     * @param dyConsumed 每次回调前后的Y差值
     */
    @Override
    public void onNestedScroll(
            @NonNull CoordinatorLayout coordinatorLayout,
            @NonNull FloatingActionButton child,
            @NonNull View target, int dxConsumed,
            int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
 
        //平移隐现
        if (dyConsumed > MIN_DY) {//上滑:消失
            showOrNot(coordinatorLayout, child, false).start();
        } else if (dyConsumed < -MIN_DY) {//下滑滑:显示
            showOrNot(coordinatorLayout, child, true).start();
        }
 
        //仅滑动时消失
//        if (dyConsumed > MIN_DY || dyConsumed < -MIN_DY) {//上滑:消失
//            showOrNot(child).start();
//        }
    }
 
    private Animator showOrNot(CoordinatorLayout coordinatorLayout, final View fab, boolean show) {
        //获取fab头顶的高度
        int hatHeight = coordinatorLayout.getBottom() - fab.getBottom() + fab.getHeight();
        int end = show ? 0 : hatHeight;
        float start = fab.getTranslationY();
        ValueAnimator animator = ValueAnimator.ofFloat(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                fab.setTranslationY((Float) animation.getAnimatedValue());
            }
        });
        return animator;
    }
 
    private Animator showOrNot(final View fab) {
        //获取fab头顶的高度
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
 
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                fab.setScaleX((Float) animation.getAnimatedValue());
                fab.setScaleY((Float) animation.getAnimatedValue());
            }
        });
        return animator;
    }
}

仔细看大佬给个 注释的....滑动时再隐藏

 

 

 

 

 

 

 

你可能感兴趣的:(学习ing)