【Android】商品详情页下拉放大动画工具类,一行代码集成使用

前言

嗨,各位看官好久不见,博文这种东西啊,真的是一个捉摸不定的事情,哈哈哈。今天给大家带来一个商城类App,或者是个人中心需要下拉页面放大headView的工具类,无图无真相。
这里写图片描述

干货

项目地址:github地址
1.在project的build文件中添加如下:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

2.然后在app的build文件依赖即可

compile 'com.github.Blincheng:PullDownEnlargeUtilDemo:v1.2'

3.使用非常简单一步集成

new PullDownEnlargeAnimUtil(findViewById(R.id.scrollView),findViewById(R.id.image));

实现步骤

总的来说是非常简单的,只要稍微有点数学计算能力~哈哈哈
1.通过事件监听来获取放大的指令.如果是顶部,继续下拉,那就放大该放大的View
2.松手后的回弹动画处理
3.简单封装,直接可以使用
4.使用干货

1.监听事件

这边我是通过setOnTouchListener(…);来监听滑动事件的,为啥不用onScroll…啥啥啥呢?因为后边要封装,当然是能兼容所有的View了,对吧!
看看代码:

@Override
            public boolean onTouch(View v, MotionEvent event) {
                initView();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_UP:
                        //手指离开后恢复图片
                        isScaling = false;
                        replayAnim();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (!isScaling) {
                            if (parentView.getScrollY() == 0) {
                                //滚动到顶部时需要记录当前位置
                                mFirstPosition = event.getY();
                            } else {
                                break;
                            }
                        }
                        int distance = (int) ((event.getY() - mFirstPosition) * 0.3); // 这边添加了一个对应滚动的系数,可以自由调节
                        if (distance < 0) {
                            break;
                        }
                        // 处理放大
                        isScaling = true;
                        ViewGroup.LayoutParams lp = childView.getLayoutParams();
                        lp.height = (int) (height + distance*MAGNIFICATION_Y);
                        lp.width = (int) (width+ distance*MAGNIFICATION_X);
                        childView.setLayoutParams(lp);
                        childView.scrollTo((int) ((distance/2)*MAGNIFICATION_X),0);
                        nowDistance = distance;
                        return true;
                }
                return false;
            }

先不看其他的代码哈,先parentView.getScrollY()去获取当前是都滚动到顶部,如果不是,那么就直接呵呵,如果事,就记录当前第一次的位置(这个位置有点重要,然后继续往下走)。之后就是计算手指滑动的距离,计算差值,更改要放大缩小的子View。还有一个重点就是我们需要的是居中放大,如果子View的外层中心是水平居中,其实不用做处理,如果不是水平居中,那么其实放大的中心点是左上角,那么同时需要我们将View向左平移二分之一的放大量,自己体会体会哈。然后如果手指弹起,那么走replayAnim();并且设置放大状态为false。

2.松手回弹动画

//松手后的回弹动画
    public void replayAnim() {
        final ViewGroup.LayoutParams lp = childView.getLayoutParams();
        final float w = childView.getLayoutParams().width;// 图片当前宽度
        final float h = childView.getLayoutParams().height;
        final float newW = width;// 图片原宽度
        final float newH = height;
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(200);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                lp.width = (int) (w - (w - newW) * cVal);
                lp.height = (int) (h - (h - newH) * cVal);
                childView.setLayoutParams(lp);
                childView.scrollTo((int) ((int) (nowDistance*(1-cVal)/2)*MAGNIFICATION_X),0);
            }
        });
        valueAnimator.start();
    }

看看代码,反向处理水平位移,看看childView.scrollTo((int) ((int) (nowDistance*(1-cVal)/2)*MAGNIFICATION_X),0);这边才是算法的精妙,数学的重要性,哈哈哈,具体叫啥来着,倒数吗~好吧,就当我乱说。缩小就不说了,简单。

3.简单的封装

最后就是封装一下,变成一个干货,可以直接拿来使用。嗯,对的,就应该是这样。小二~上全部代码!

public class PullDownEnlargeAnimUtil {
    /**
     * 要放大的子View
     * */
    private View childView;
    /**
     * 监听滚动事件的父View
     * */
    private View parentView;
    /**
     * X方向放大的倍率
     * */
    private float MAGNIFICATION_X = 1.0f;
    /**
     * Y方向放大的倍率
     * */
    private float MAGNIFICATION_Y = 1.0f;
    /**
     * 是否正在放大
     * */
    private boolean isScaling;
    /**
     * 记录首次按下位置
     * */
    private float mFirstPosition = 0;
    /**
     * 下拉偏移量(主要用来逆向位移)
     * */
    private int nowDistance;
    /**
     * 要放大控件的初始宽高,第一次初始化在第一次走onTouch()的时候
     * */
    private int width = 0;
    private int height = 0;

    public PullDownEnlargeAnimUtil(View parentView,View childView){
        this.childView = childView;
        this.parentView = parentView;
        initEvent();
    }
    private void initEvent(){
        parentView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                initView();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_UP:
                        //手指离开后恢复图片
                        isScaling = false;
                        replayAnim();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (!isScaling) {
                            if (parentView.getScrollY() == 0) {
                                //滚动到顶部时需要记录当前位置
                                mFirstPosition = event.getY();
                            } else {
                                break;
                            }
                        }
                        int distance = (int) ((event.getY() - mFirstPosition) * 0.3); // 这边添加了一个对应滚动的系数,可以自由调节
                        if (distance < 0) {
                            break;
                        }
                        // 处理放大
                        isScaling = true;
                        ViewGroup.LayoutParams lp = childView.getLayoutParams();
                        lp.height = (int) (height + distance*MAGNIFICATION_Y);
                        lp.width = (int) (width+ distance*MAGNIFICATION_X);
                        childView.setLayoutParams(lp);
                        childView.scrollTo((int) ((distance/2)*MAGNIFICATION_X),0);
                        nowDistance = distance;
                        return true;
                }
                return false;
            }
        });
    }
    private void initView(){
        if(width == 0||height == 0){
            width = childView.getWidth();
            height = childView.getHeight();
        }
    }
    //松手后的回弹动画
    public void replayAnim() {
        final ViewGroup.LayoutParams lp = childView.getLayoutParams();
        final float w = childView.getLayoutParams().width;// 图片当前宽度
        final float h = childView.getLayoutParams().height;
        final float newW = width;// 图片原宽度
        final float newH = height;
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(200);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                lp.width = (int) (w - (w - newW) * cVal);
                lp.height = (int) (h - (h - newH) * cVal);
                childView.setLayoutParams(lp);
                childView.scrollTo((int) ((int) (nowDistance*(1-cVal)/2)*MAGNIFICATION_X),0);
            }
        });
        valueAnimator.start();
    }
}

使用干货

那么封装好了,怎么用呢?
一行代码解决,如下:

//第一个参数是滚动布局,其实就是提供滑动监听的依赖布局,其实并不一定是福布局。
//第二个参数是需要放大的View,理论上可以是任何View,可以在任何布局里面。
new PullDownEnlargeAnimUtil(parentView,childView);

总结

东西整体来说不难的,但是要自己从0开始写,那也还是需要一些时间和一些思考的,有些东西还是要调一调,折腾一下才能出来的,虽然东西不难,就是需要思路。本次项目代码就不上传到github了,就一个类,已经贴在上面,大家如果有需要直接拷贝就是了。如果有什么问题欢迎大家留言或e我哦,随时欢迎,下次再见。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值