Android模仿快手视频详情页退出动画

转载请注明出处,谢谢:https://blog.csdn.net/HarryWeasley/article/details/89449919

源码地址为:https://github.com/HarryWeasley/KuaishouDemo

首先看快手的动图展示

在这里插入图片描述

然后是我做的demo动图效果
在这里插入图片描述

前因:作为一个中二中年人,某次机缘巧合之下,下载了快手这个app,然后发现了他这个动画,就觉得这个动画运用的地方挺多的,微信的图片退出动画也是这个,所以决定如何实现该功能。

其实本篇文章的难度并不是很大,主要是解决的一个思路问题。

首先第一个要使用转场动画:

    Intent intent = new Intent(MainActivity.this, DetailActivity2.class);
                intent.putExtra("url",datas.get(position));
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, v, "sharedView").toBundle());

要在xml中加入

     android:transitionName="sharedView"

转场动画不是本文的重点,不会详细描述。

当我们滑动视图,让视图跟着手指的操作而滑动的时候,可以使用GestureDetector类实现,在onScroll方法中回调,进行滑动操作。

在实现GestureDetector.OnGestureListener方法的时候,一定要将onDown方法的返回值变为true,否则可能onScroll方法不会被执行

视图的变大变小,使用view.setScaleX方式来实现

视图的滚动滑动,使用view.setTranslationX方式来实现

而视图的背景,使用一个自定义的TypeEvaluator来实现

代码如下所示:

  @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if (parent == null) {
            parent = getChildAt(0);
        }
        if (viewHeight == 0) {
            viewHeight = parent.getHeight();
        }
        float moveX = e2.getX() - e1.getX();
        float moveY = e2.getY() - e1.getY();

        mExitScalingRef = 1;
        mExitScalingRef = mExitScalingRef - moveY / viewHeight;
        parent.setTranslationX(moveX);
        parent.setTranslationY(moveY);
        parent.setScaleX(mExitScalingRef);
        parent.setScaleY(mExitScalingRef);
        if (mExitScalingRef > 1) {
            //当用户往上滑动的时候
            frameLayout.setBackgroundColor(mColorEvaluator.evaluate(2 - mExitScalingRef, 0x00000000, 0xFF000000));
        } else {
            //当用户往下滑动的时候
            frameLayout.setBackgroundColor(mColorEvaluator.evaluate(mExitScalingRef, 0x00000000, 0xFF000000));
        }
        return false;
    }

其中mColorEvaluator的实现代码如下所示:


     TypeEvaluator<Integer> mColorEvaluator = new TypeEvaluator<Integer>() {
        @Override
        public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
            int startColor = startValue;
            int endColor = endValue;

            int alpha = (int) (Color.alpha(startColor) + fraction * (Color.alpha(endColor) - Color.alpha(startColor)));
            int red = (int) (Color.red(startColor) + fraction * (Color.red(endColor) - Color.red(startColor)));
            int green = (int) (Color.green(startColor) + fraction * (Color.green(endColor) - Color.green(startColor)));
            int blue = (int) (Color.blue(startColor) + fraction * (Color.blue(endColor) - Color.blue(startColor)));
            return Color.argb(alpha, red, green, blue);
        }
    };

当我们松开手指,来判断缩小的进度,当小于某个进度值的时候,退出该activity,否则执行返回动画:

  @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (mExitScalingRef < DEFAULT_EXIT_SCALE) {
                //缩小到一定的程度,将其关闭
                if (finishListener != null) {
                    finishListener.finish();
                }
            } else {
                //如果拉动距离不到某个角度,则将其动画返回原位置
                final float moveX = parent.getTranslationX();
                final float moveY = parent.getTranslationY();
                final float scaleX = parent.getScaleX();
                final float scaleY = parent.getScaleY();
                ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
                valueAnimator.setDuration(500);
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float p = (float) animation.getAnimatedValue();
                        float animationMoveX = moveX + (0 - moveX) * p;
                        parent.setTranslationX(animationMoveX);
                        parent.setTranslationY(moveY + (0 - moveY) * p);
                        parent.setScaleX(scaleX + (1 - scaleX) * p);
                        parent.setScaleY(scaleY + (1 - scaleY) * p);
                    }
                });
                valueAnimator.start();
            }
        }
        return mGestureDetector.onTouchEvent(event);
    }

为了使该控件更有集成性,我自定义了一个FrameLayout,AnimationFrameLayout

在Activity的xml布局中只是放一个com.example.kuaishoudemo.AnimationFrameLayout控件

然后在onCreate方法中,通过以下的方式,来实现真正的视图

        AnimationFrameLayout frameLayout = findViewById(R.id.frame_layout);
        //将内部的布局item_linear_layout,放入AnimationFrameLayout中
        View view = LayoutInflater.from(this).inflate(R.layout.item_linear_layout, frameLayout);
        frameLayout.setDefaultExitScale(0.8f);
        ImageView imageView = view.findViewById(R.id.image);
        String url = getIntent().getStringExtra("url");
        Glide.with(this).load(url).into(imageView);
        frameLayout.setFinishListener(new AnimationFrameLayout.FinishListener() {
            @Override
            public void finish() {
                onBackPressed();
            }
        });

文章源码地址在上部,具体的源码信息,大家去github下载下来看就可以了,谢谢。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值