【Android 動畫】動畫詳解之仿微信檢視大圖效果(四)

歡子發表於2019-02-26

前幾篇中,我們說了安卓的補間動畫和插值器,這一篇,我們來寫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);
複製程式碼

最後獻上原始碼 github

你的認可,是我堅持更新部落格的動力,如果覺得有用,就請點個贊,謝謝

相關文章