安卓复杂滑动案例 自定义behavior源码分析 实现头布局图片的缩放透明度变化,RecycleView的滑动布局,坐标变化

来源:互联网 发布:ipad有淘宝卖家版吗 编辑:程序博客网 时间:2024/05/29 03:22


#复杂滑动案例

上方图片放大,
透明
输入框,不断增大
    * 变色
滑动的时候,条目不会改变.
    * 再滑的时候,条目滑动


1,让rv居于头部的下方
    * 方案?:
    * 1,重写layoutDependsOn 让当前rv去以来头部视图
    * 2,获取都以来的头部视图的高度onDependentViewChanged 设置给rv 设置setTranslationY
2,让rv跟着头部 向上平移
处理头部的向上平移:在onNestedPreScroll中计算移动距离,还没有真正移动
    * float newTranslationY = dependency.getTranslationY() - dy;
            //计算出最小平移的y的距离

            float minTranslationY = -(dependency.getHeight() - finalHeight);
            if (newTranslationY > minTranslationY) {
                dependency.setTranslationY(newTranslationY);
                /**
                 * 在图片折叠的情况下
                 * 1不允许RecycleView自身滚动,不能和图片一起平移
                 * 2只能和图片一起向上移动
                 */
                //1,
                consumed[1] = dy;
                //2,
            }
3,rv向上平移  
    onDependentViewChanged
     child.setTranslationY(dependency.getHeight()+dependency.getTranslationY());
    后面是一个负数,所以用+号
4,向下平移的处理,
*  onNestedScroll方法中
*  float newTranslation = dependency.getTranslationY() - dyUnconsumed;
        //平移的最大距离,坐标0
        if (newTranslation <0) {
            dependency.setTranslationY(newTranslation);
        }
5处理图片的缩放和透明都,变化
    * onDependentViewChanged中拿到移动百分比,
    * 按照百分比,进行图片的缩放,和透明度变化
6,手指快读滑动图片的缓慢打开和关闭 

    * 快速滑动 


<?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"    >    <ImageView        android:src="@drawable/header"        android:scaleType="centerCrop"        android:id="@+id/iv"        android:layout_width="match_parent"        android:layout_height="300dp" />    <android.support.v7.widget.RecyclerView        android:background="#efffffff"        app:layout_behavior="@string/HeaderScrollBehavior"        android:id="@+id/rv"        android:layout_width="match_parent"        android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></android.support.design.widget.CoordinatorLayout>

package com.example.yangg.commplexscrol;import android.content.Context;import android.os.Handler;import android.support.design.widget.CoordinatorLayout;import android.support.v4.view.ViewCompat;import android.support.v7.widget.RecyclerView;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.widget.Scroller;/** * Created by yangg on 2017/7/6. */public class HeaderScrollBehavior extends CoordinatorLayout.Behavior<RecyclerView> {    private View dependency;    private final Scroller mSroller;    public HeaderScrollBehavior(Context context, AttributeSet attrs) {        super(context, attrs);        mSroller = new Scroller(context);    }    /**     * 去定当前空间rv 以来的是哪个子试图     */    @Override    public boolean layoutDependsOn(CoordinatorLayout parent, RecyclerView child, View dependency) {        if (dependency.getId() == R.id.iv) {            this.dependency = dependency;            return true;        }        return false;    }    /**     * 依赖的视图变化     *     * @param parent     * @param child     * @param dependency     * @return rv 就是child     * rvy轴上平移一段距离:移动图片的高度     * <p>     * 1,图片向上折叠     */    @Override    public boolean onDependentViewChanged(CoordinatorLayout parent, RecyclerView child, View dependency) {        //把图片移动的高度给rv 图片走多少,rv就走多少        child.setTranslationY(dependency.getHeight() + dependency.getTranslationY());        /**         * 在这个方法中控制图片的变化         * 计算出移动的百分比,,图片就缩放百分之多少         *         */        float persent = Math.abs(dependency.getTranslationY() / (dependency.getHeight() - finalHeight));        dependency.setScaleX(1 + persent);        dependency.setScaleY(1 + persent);        dependency.setAlpha(1 - persent);        return true;    }    /**     * 判断 在嵌套滚动将要开始的时候,一般用于判断滚动方向  顺序1!!!     *     * @param coordinatorLayout     * @param child     * @param directTargetChild     * @param target     * @param nestedScrollAxes     * @return     */    @Override    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, RecyclerView child, View directTargetChild, View target, int nestedScrollAxes) {        //判断垂直滚动,,滚动之前 告诉系统,垂直滚动        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;    }    private float finalHeight = 150;    /**     * 在滚动之前,告诉系统,  要滚动的距离,dy     * onStartNestedScroll 之后  顺序2!!!     * 在嵌套滚动之前执行,这个方法在在onStartNestedScroll 执行     * dy:y方向上移动的距离,值得是单位时间内手指移动的距离     *     * @param coordinatorLayout     * @param child     * @param target     * @param dx     * @param dy     * @param consumed          :十一恶搞数组:消耗的xy的距离     *                          0元素:表示x方向系统小号的距离     *                          1元素:表示y方向系统消耗 的距离     */    @Override    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, RecyclerView child, View target, int dx, int dy, int[] consumed) {        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);        //判断手指向下移动dy<=0  向上移动dy>0        if (dy <= 0) {            return;        }        //计算他移动了多少        float newTranslationY = dependency.getTranslationY() - dy;        //计算出最小平移的y的距离        float minTranslationY = -(dependency.getHeight() - finalHeight);        if (newTranslationY > minTranslationY) {            dependency.setTranslationY(newTranslationY);            /**             * 在图片折叠的情况下             * 1不允许RecycleView自身滚动,不能和图片一起平移             * 2只能和图片一起向上移动             */            //1,            consumed[1] = dy;            //2,        }    }    /**     * 开始滚动                 顺序3!!!     * rv 消耗掉,y方向上的距离,dyUnconsumed不等于0     *     * @param coordinatorLayout     * @param child     * @param target     * @param dxConsumed     * @param dyConsumed     * @param dxUnconsumed     * @param dyUnconsumed     */    @Override    public void onNestedScroll(CoordinatorLayout coordinatorLayout, RecyclerView child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);        //Log.i("test", "dy--->" + dyConsumed);        Log.i("test", "dyUnconsumed" + dyUnconsumed);        /**         * 向下移动dyUnconsumed <0的时候         */        if (dyUnconsumed > 0) {            return;        }        float newTranslation = dependency.getTranslationY() - dyUnconsumed;        //平移的最大距离,坐标0        if (newTranslation <= 0) {            dependency.setTranslationY(newTranslation);        }    }    /**     * Fling 快速滑动,执行, 猛动     *     * @param coordinatorLayout     * @param child     * @param target     * @param velocityX     * @param velocityY  表示快速滑动松开收瞬间y方向的的速度,向上为+ ,向下喂-     * @return     */    //定义 boolean,判断是否自动滚动中,,    private boolean isScrolling = false;    @Override    public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, RecyclerView child, View target, float velocityX, float velocityY) {        Log.i("test", "velocityY" + velocityY);        if (!isScrolling) {            return startExpandOrClose(velocityY);        }        Log.i("test", "onNestedPreFling");        return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);    }    /**     * 慢慢滚动的时候走这里     *  父布局布局停止滚动的时候,执行一次,     *  手指停了之后,又执行一次     * @param coordinatorLayout     * @param child     * @param target     */    @Override    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, RecyclerView child, View target) {        super.onStopNestedScroll(coordinatorLayout, child, target);       //800以下都可以,表示速度很慢        startExpandOrClose(0);        Log.i("test","onStopNestedScroll");    }    //在滚动被子视图接受的时候执行    @Override    public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, RecyclerView child, View directTargetChild, View target, int nestedScrollAxes) {        super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);        //如果我滑动的过程中的时候停止了,但是没有松开收调用onNestedScrollAccepted        //继续滑动-->停止-->onNestedScrollAccepted        //再执行,-->松开-->onNestedScrollAccepted  最后一次执行这个方法onNestedScrollAccepted        //手指松开的一瞬间,我才真正停止,滚动了,        //让动画禁止执行  ,,第二次不会被调用,第二次,的时候不影响上个方法,执行        mSroller.abortAnimation();    }    private boolean startExpandOrClose(float velocityY) {        //获取松开收瞬间,图片已经平移的距离        float translationY = dependency.getTranslationY();        float upFinalTranslationY = -(dependency.getHeight() - finalHeight);        float downFinalTranslationY = 0;        //dingyi boolean值却动是否闭合的状态fun        boolean isClose = false;        if (Math.abs(velocityY) <= 800) {            /**             * 滑动过成中慢慢的抬起手,             * 判断松开收时已经平移的位置 和 最向上品故意位置的差值的据对只进行比较             */            if (Math.abs(translationY) < Math.abs(translationY - upFinalTranslationY)) {                isClose = false;            } else {                isClose = true;            }        } else {            /**             * 快速滑动             */            if (velocityY > 0) {//向上滑动                //东松开收的钝剑位置自动滚动到完全闭合的位置                isClose = true;            } else {//向下滑动                //完全展开                isClose = false;            }        }        //确定滚动的目标点        float targetTranslationY = isClose ? upFinalTranslationY : downFinalTranslationY;        int starY = (int) translationY;        //变化的        int dy = (int) (targetTranslationY - translationY);        mSroller.startScroll(0, starY, 0, dy);        handler.post(flingRunable);        isScrolling = true;        /**         * ?????????????????????         */        return true;    }    private Handler handler = new Handler();    private Runnable flingRunable = new Runnable() {        @Override        public void run() {            //Scroller滚滚的用户那里//            是一阵一帧的向前滚动的,眼不断的计算是否滚动到目标,如果未滚动到,则据需滚动            //判断scroller是否滚动到莫表            //这个方法还可以判断是否有一个新的小目标点            if (mSroller.computeScrollOffset()) {                //mSroller.getCurrY() 指获取下一个新的位置                dependency.setTranslationY(mSroller.getCurrY());                handler.post(this);            }        }    };}

阅读全文
1 0
原创粉丝点击