美文网首页
【Android 动画】动画详解之仿微信查看大图效果(四)

【Android 动画】动画详解之仿微信查看大图效果(四)

作者: 欢子3824 | 来源:发表于2018-12-04 17:22 被阅读0次

    前几篇中,我们说了安卓的补间动画和插值器,这一篇,我们来写2个例子。

    一、小球落地动画

    先上效果图:

    20181204_162703.gif
    可以看到,小球是先加速下落,碰到底部后弹起,再下落,最后完全静止,如果要手写这个过程,还是相当麻烦的,有没有简单的办法?
    这里就要用到我们第2篇中说到过的BounceInterpolator插值器。 详情请看【Android 动画】动画详解之插值器(二)
            translateAnimation = new TranslateAnimation(0, 0, 0, DensityUtils.dp2px(BallActivity.this, 400));
            translateAnimation.setDuration(2000);
            translateAnimation.setFillAfter(true);
            translateAnimation.setInterpolator(new BounceInterpolator());
            tvDemo.startAnimation(translateAnimation);
    

    二、仿微信查看大图效果

    相信大家都有留意微信的查看大图动画,它会由图片当前在屏幕中的位置渐渐放大移动到屏幕中心,简单来说的话就是一个缩放+透明度动画。
    先上效果图:


    20181204_164723.gif

    之前在第一篇中,我们说过,缩放动画的取值可以是具体数值、相对于自身、相对于父布局这3种,这里就需要使用相对于父布局这种。

    首先,我们需要获取点击按钮在屏幕中的坐标。先定义一个int数据用于存放坐标,然后调用getLocationOnScreen方法即可获取该控件在屏幕中的坐标

      int[] location = new int[2];
      btnTopLeft.getLocationOnScreen(location);
    

    然后,计算该坐标相对于屏幕的百分比

            pointx = getIntent().getIntExtra(POINTX, 0);
            pointy = getIntent().getIntExtra(POINTY, 0);
    
            DisplayMetrics metrics = getResources().getDisplayMetrics();
            if (pointx == 0) {
    
                pointXValue = 0.5f;
            } else {
                pointXValue = pointx / metrics.widthPixels;
    
            }
            if (pointy == 0) {
                pointYValue = 0.5f;
            } else {
                pointYValue = pointy / metrics.heightPixels;
            }
    

    添加动画

            AnimationSet animationSet = new AnimationSet(true);
    
    
            AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
    
            ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1f, 0, 1f, ScaleAnimation.RELATIVE_TO_PARENT,
                    pointXValue, ScaleAnimation.RELATIVE_TO_PARENT, pointYValue);
            animationSet.addAnimation(alphaAnimation);
            animationSet.addAnimation(scaleAnimation);
    
            animationSet.setDuration(500);
            animationSet.setFillAfter(true);
            ivImg.startAnimation(animationSet);
    

    处理返回,重写onBackPressed方法,返回时,与进入的动画正好相反

    
        @Override
        public void onBackPressed() {
    
            AnimationSet animationSet = new AnimationSet(true);
    
    
            AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
    
            ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0, 1f, 0, ScaleAnimation.RELATIVE_TO_PARENT,
                    pointXValue, ScaleAnimation.RELATIVE_TO_PARENT, pointYValue);
            animationSet.addAnimation(alphaAnimation);
            animationSet.addAnimation(scaleAnimation);
    
            animationSet.setDuration(500);
            animationSet.setFillAfter(true);
            animationSet.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                    ImgActivity.super.onBackPressed();
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    
            ivImg.startAnimation(animationSet);
    
        }
    

    还需要处理默认的Activity切换动画,以及Activity的默认背景

            startActivity(intent);
            overridePendingTransition(0, 0);
    

    设置目标Activity的主题

            <activity
                android:name=".demo.ImgActivity"
                android:theme="@style/transparent"></activity>
    
      <style name="transparent" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="android:windowIsTranslucent">true</item>
            <item name="android:windowBackground">@android:color/transparent</item>
        </style>
    

    当我们运行时会发现,动画的起始位置是按钮的左上角,原来使用getLocationOnScreen获取的是控件左上角的坐标,所以我们需要加上控件宽高的1/2
    TIP:由于此处所有按钮的宽高都一样,所以就取了同一个。

           Intent intent = new Intent(WXPicActivity.this, ImgActivity.class);
            int[] location = new int[2];
    
            switch (view.getId()) {
                case R.id.btn_top_left:
                    btnTopLeft.getLocationOnScreen(location);
                    break;
                case R.id.btn_top_right:
                    btnTopRight.getLocationOnScreen(location);
                    break;
                case R.id.btn_bottom_left:
                    btnBottomLeft.getLocationOnScreen(location);
                    break;
                case R.id.btn_bottom_right:
                    btnBottomRight.getLocationOnScreen(location);
                    break;
                case R.id.btn_center:
                    btnCenter.getLocationOnScreen(location);
                    break;
            }
            intent.putExtra(ImgActivity.POINTX, location[0] + btnCenter.getMeasuredWidth() / 2);
            intent.putExtra(ImgActivity.POINTY, location[1] + btnCenter.getMeasuredHeight() / 2);
            startActivity(intent);
            overridePendingTransition(0, 0);
    

    效果更流畅的方案,请移步
    【Android视图效果】共享元素实现仿微信查看大图效果

    最后献上源码 github

    相关文章

      网友评论

          本文标题:【Android 动画】动画详解之仿微信查看大图效果(四)

          本文链接:https://www.haomeiwen.com/subject/fwfvcqtx.html