Android 实现页面顶部下拉、底部上拉 沿着Y轴缩放效果

0.补一张效果图。


1.仅对ScrollView 和RecyclerView 进行顶部下拉,底部上拉实现类似小米页面,页面到达最底部,继续向下拉动时,或者页面到达最底部继续向上拉动时产生的沿着Y轴的缩放效果。

2.原理:以ScaleRecyclerView 为例,创建ScaleRecyclerView 继承至RecyclerView 。

3.重写dispatchTouchEvent()方法。当滑动调用dispatchTouchEvent时 不断检测View自身的状况。

4.在合适的时候让View进行Y轴的缩放即可。

5.这个给出ScaleRecyclerView 和ScaleScrollView 代码。

6.详细的看代码注释。

package com.yushilei.animatorscale.widget;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.yushilei.animatorscale.RAdapter;

/**
 * @author by  yushilei.
 * @time 2016/9/8 -11:01.
 * @Desc
 */
public class ScaleRecyclerView extends RecyclerView {
    public ScaleRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    String TAG = "ScaleRecyView";
    /**
     * action down 产生的x,y坐标
     */
    float lastX;
    float lastY;
    /**
     * 当前View是否处于缩放状态
     */
    boolean isScale = false;
    /**
     * 当前View的缩放值
     */
    float mScale = 1.0f;
    /**
     * 产生缩放时,使用的缩放系数,该值越大缩放比率就越大
     */
    float scaleRatio = 0.7f;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        float y = ev.getY();

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录Down时的 x y
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                if (y - lastY > 0) {
                    //获取Recycler的第一个展示的View
                    View view = getChildAt(0);
                    int pos = ((RAdapter.VH) view.getTag()).getPos();
                    //获取该View对应在数据集合中的位置
                    //如果位置=0 并且该View的上边界=0 并且当前正在向下拉动
                    if (pos == 0 && view.getTop() >= 0) {
                        //计算偏移量
                        float distance = y - lastY;
                        //计算出要缩放的scale
                        mScale = 1 + distance * scaleRatio / getHeight();
                        //设置缩放的锚点
                        setPivotY(0f);
                        setPivotX(getWidth() / 2);
                        //进行缩放
                        ViewCompat.setScaleY(this, mScale);
                        isScale = true;
                    }
                } else {
                    //获取最后一个展示的View
                    int count = getChildCount();
                    View lastView = getChildAt(count - 1);
                    int pos = ((RAdapter.VH) lastView.getTag()).getPos();
                    //判断其是否为数据集合最后一个位置
                    if (pos + 1 == getAdapter().getItemCount() && lastView.getBottom() <= getBottom()) {
                        //滑动到最底部 向上拉
                        float distance = y - lastY;
                        mScale = 1 - scaleRatio * distance / getHeight();
                        //设置锚点
                        setPivotX(getWidth() / 2);
                        setPivotY(getHeight());
                        ViewCompat.setScaleY(this, mScale);
                        isScale = true;
                    }
                }


                break;
            case MotionEvent.ACTION_UP:
                if (isScale) {
                    //如果已经进行了缩放,up的时候应该恢复原状,从当前scale 恢复至1.0f
                    ObjectAnimator animator = ObjectAnimator.ofFloat(this, "scaleY", mScale, 1.0f);
                    animator.setDuration(300);
                    animator.start();
                    isScale = false;
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
}

7. ScaleScrollView 代码。

package com.yushilei.animatorscale.widget;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * @author by  yushilei.
 * @time 2016/9/8 -10:08.
 * @Desc
 */
public class ScaleScrollView extends ScrollView {
    public ScaleScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    float lastX;
    float lastY;
    String TAG = "ScaleScrollView";
    boolean isScale = false;

    float mScale = 1.0f;

    float scaleRatio = 0.7f;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        float y = ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:

                if (getScrollY() == 0 && y - lastY > 0) {
                    //向下拉动
                    float distance = y - lastY;
                    int height = getHeight();
                    mScale = 1 + distance * scaleRatio / height;
                    setPivotY(0f);
                    setPivotX(getWidth() / 2);
                    ViewCompat.setScaleY(this, mScale);
                    isScale = true;
                } else {
                    //滑动到最底部 向上拉
                    int childHeight = getChildAt(0).getHeight();
                    int height = getHeight();
                    if (getScrollY() >= childHeight - height && y - lastY < 0) {
                        float distance = y - lastY;
                        mScale = 1 - scaleRatio * distance / height;
                        setPivotY(getHeight());
                        setPivotX(getWidth() / 2);
                        ViewCompat.setScaleY(this, mScale);
                        isScale = true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isScale) {
                    ObjectAnimator animator = ObjectAnimator.ofFloat(this, "scaleY", mScale, 1.0f);
                    animator.setDuration(300);
                    animator.start();
                    isScale = false;
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

}

8. 效果可以去看下小米手机 页面到达顶部 下拉 ,或者页面到达最底部 上来的样式 。完~~

你可能感兴趣的:(Android 实现页面顶部下拉、底部上拉 沿着Y轴缩放效果)