用開源項目ActivityOptionsICS讓ActivityOptions的動畫實現兼容


我之前寫過一篇文章是講解ActivityOption的api方法的(http://www.cnblogs.com/tianzhijiexian/p/4087917.html),當時吐槽各種動畫不兼容,完全無視我們4.x或者2.x用戶嘛,好在有開源庫來幫助我們實現動畫。

開源項目地址:https://github.com/tianzhijiexian/ActivityOptionsICS

 

零、修改style

用這些動畫之前,需要對應用的style進行修改,添加一個屬性

<item name="android:windowIsTranslucent">true</item>  

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- 允許使用transitions -->  
         <item name="android:windowIsTranslucent">true</item>  
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>

 

一、ActivityOptionsCompatICS

提供了和ActivityOptions、ActivityCompat基本一致的方法來實現相同的動畫效果,總共有如下方法。

【注意】這個類必須在view都顯示完成后才能使用,可以在點擊事件中中或者是用post一個runnable來用。

(1)public static ActivityOptionsCompatICS makeCustomAnimation(Context context,

int enterResId, int exitResId)

參數:

enterId:進入動畫的資源ID

exitId:退出動畫的資源ID

設置自定義的Activity動畫,出入的是動畫資源的id。

這個方法和overridePendingTransition(R.anim.slide_bottom_in, android.R.anim.fade_out);十分類似,傳入一個進入的動畫和一個退出的動畫即可

    public void customAnim() {
        ActivityOptionsCompatICS options = ActivityOptionsCompatICS.makeCustomAnimation(this,
                R.anim.slide_right_in, R.anim.slide_bottom_out);
        ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
    }

 

(2)public static ActivityOptionsCompatICS makeScaleUpAnimation(View source, int startX,

int startY, int width, int height)

參數:

source:一個view對象,用戶確定新activity啟動的初始坐標

startX:新activity出現的初始X坐標,這個坐標是相對於source的左上角X坐標

startY:新activity出現的初始Y坐標,這個坐標相對於source的左上角Y坐標

width:新activity初始的寬度

height:新activity初始的高度

通過看源碼可以很容易理解這些參數的意義

        int[] pts = new int[2];//ps = position,目的得到當前view相對於屏幕的坐標
        source.getLocationOnScreen(pts);
        // 設置起始坐標和起始寬高
        opts.mStartX = pts[0] + startX;
        opts.mStartY = pts[1] + startY;
        opts.mWidth = width;
        opts.mHeight = height;

實現的效果是:新的Activity從某個位置以某個大小出現,然后慢慢拉伸漸變到整個屏幕

public void scaleUpAnim(View view) {
        ActivityOptionsCompatICS options = ActivityOptionsCompatICS.makeScaleUpAnimation(view,
                 0, 0, //拉伸開始的坐標
                 view.getMeasuredWidth(), view.getMeasuredHeight());//初始的寬高
        ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
    }

 

(3)public static ActivityOptionsCompatICS makeThumbnailScaleUpAnimation(View source, 

Bitmap thumbnail, int startX, int startY) 

參數:

source:一個view對象,用來確定起始坐標

thumbnail:一個bitmap對象,新的activity將通過這個bitmap漸變拉伸出現,新的activity初始大小就是這個bitmap的大小

startX:新activity初始的X坐標,相對於source左上角的X來說的

startY:新的activity初始的Y坐標,相對於source左上角Y坐標來說的

效果是:一個bitmap慢慢從某個位置拉伸漸變新的activity

public void thumbNailScaleAnim(ImageView view) {
        view.setDrawingCacheEnabled(true);
         Bitmap bitmap = view.getDrawingCache();
          ActivityOptionsCompatICS options = ActivityOptionsCompatICS.makeThumbnailScaleUpAnimation(
            view, bitmap, 0, 0);
          // Request the activity be started, using the custom animation options.
          ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
          //view.setDrawingCacheEnabled(false);
    }

 

(4)public static ActivityOptionsCompatICS makeSceneTransitionAnimation(Activity activity, 

final View sharedElement,int sharedElementId)

參數:

activity:當前activity的對象

sharedElement:一個view對象,用來和新的activity中的一個view對象產生動畫

sharedElemetId:新的activity中的view的Id,這個view是用來和原始activity中的view產生動畫的

效果是:原始activity中的一個view隨着新activity的慢慢啟動而移動到新的activity中,實現補間動畫

public void screenTransitAnim(View v,int id) {
        ActivityOptionsCompatICS options = ActivityOptionsCompatICS.
                makeSceneTransitionAnimation(this, v,id);
        ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
    }

 

(5)public static ActivityOptionsCompatICS makeSceneTransitionAnimation(Activity activity,

Pair<View, Integer>... sharedElements)

參數:

activity:當前的activity

sharedElements:Pair對象,上面的一個方法是實現單一view的動畫,這里可以有多個view對象進行動畫

screenTransitAnimByPair(
                    Pair.create((View)orginalImageView, R.id.target_imageView),
                    Pair.create((View)orginalTextView, R.id.target_textView),
                    Pair.create((View)chromeIView, R.id.target_chrome_imageView));

 

    @SuppressWarnings("unchecked")
    public void screenTransitAnimByPair(Pair<View, Integer>... views) {
        ActivityOptionsCompatICS options = ActivityOptionsCompatICS.makeSceneTransitionAnimation(
                MainActivity.this, views);
        ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
    }

 

二、ActivityCompatICS

這個類僅僅提供了啟動activity的方法,很簡單就一個靜態方法

public static void startActivity(Activity activity, Intent intent, Bundle bundle) 

傳入的bundle是ActivityOptionsCompatICS通過toBundle()方法產生的bundle對象

 

三、TransitionCompat

這個類是用在新的activity中接收動畫的,在新的activity的setContentView()后寫

TransitionCompat.startTransition(this, R.layout.activity_target);即可。

這里的參數一個是activity對象,一個是當前activity的布局文件

在新activity的onBackPressed()方法中寫上TransitionCompat.finishAfterTransition(this);就可以實現退出時的動畫了。

當然這個類提供了各種設置方法:

     TransitionCompat.addListener(transitionListener);
        TransitionCompat.addViewAnimListener(viewAnimListener);
        TransitionCompat.setEnterTransition(new SceneFade(this, true));// use to scale Up animation
     TransitionCompat.setExitTransition(animation)//在onBackPressed中設置
TransitionCompat.setAnimDuration(300);// default TransitionCompat.setAnimStartDelay(0);// default
     TransitionCompat.setTimeInterpolator(new AccelerateDecelerateInterpolator());// default

1.設置屏幕動畫監聽器

2.設置view動畫的監聽器(用於bitmap,sharedElements動畫),監聽器中可以得到view的對象和id

3.設置屏幕進入時的效果,這里傳入的是個繼承自TransitionAnims的實現類,這個我們下面再說

4.設置屏幕退出時的效果,這里傳入的是個繼承自TransitionAnims的實現類

5.設置動畫的持續時間

6.設置動畫的延遲時間

7.設置動畫的變化效果

 

四、TransitionAnims

這個TransitionAnims是一個實現屏幕動畫的抽象類,里面實現了各種初始化和收尾操作,並且添加了常用的監聽器。如果我們想自己對屏幕進行動畫效果的設定,只需要繼承這個類然后實現方法即可。

package com.example.activityoptionsjbtest;

import android.app.Activity;

import com.kale.activityoptions.transition.TransitionAnims;

public class SceneAnimTest extends TransitionAnims{

    public SceneAnimTest(Activity activity) {
        super(activity);
        // TODO 自動生成的構造函數存根
    }

    @Override
    public void playScreenEnterAnims() {
        // TODO 自動生成的方法存根
        
    }

    @Override
    public void playScreenExitAnims() {
        // TODO 自動生成的方法存根
        
    }

}

 

我們來看看這個類中我們可以得到什么東西。

        getActivity();//得到要啟動動畫的activity
        getAnimsDuration();//得到通過transitionCompatICS設置的動畫持續時間
        getAnimsInterpolator();//得到通過transitionCompatICS設置的動畫效果
        getBackground();//得到當前activity默認的背景圖片,這個是開源項目中默認設置的,是一個#eeeeee的drawable。僅僅用於收尾操作
        getAnimsStartDelay();////得到通過transitionCompatICS設置的動畫延遲時間
        //廢棄//getIsEntireScreenAnim();////得到當前是否是讓整個屏幕執行動畫,如果不是那么就是讓activity的actionbar下方的view執行動畫
        getSceneRoot();//重要:執行動畫的view對象。

 

這里面還有一個動畫監聽器,我們繼承這個類后可以直接用這個監聽器來實現動畫監聽操作。比如原始項目中用於屏幕漸變操作的類就用到了這個監聽器。如果不用這個監聽器,那么transitionCompatICS設置的屏幕監聽器是監聽不到動畫的。

其中還有兩個收尾方法:

enterAnimsEnd(); // 在進入動畫結束后請自行調用

exitAnimsEnd(); // 在退出動畫結束后請自行調用

片段:

AnimatorSet set = new AnimatorSet();
        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(getSceneRoot(), "alpha", fromAlpha, toAlpha);
        set.addListener(new TransitionAnimsListener() {
            @Override
            public void onAnimationEnd(Animator animator) {
                // TODO 自動生成的方法存根
                super.onAnimationEnd(animator);
                if (isEnter) {
                    enterAnimsEnd();
                }else {
                    exitAnimsEnd();
                }
            }
        });

 

原始項目中使用這個類的例子(漸變效果):

package com.kale.activityoptions.anim;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;

import com.kale.activityoptions.transition.TransitionAnims;

public class SceneFade extends TransitionAnims{
    
    public SceneFade(Activity activity) {
        super(activity);
        // TODO 自動生成的構造函數存根
    }

    public void playScreenAnims(final boolean isEnter) {
        float fromAlpha,toAlpha;
        if (isEnter) {
            fromAlpha = 0f;
            toAlpha = 1f;
        }else {
            fromAlpha = 1f;
            toAlpha = 0f;
        }
        
        // TODO 自動生成的方法存根
        AnimatorSet set = new AnimatorSet();
        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(getSceneRoot(), "alpha", fromAlpha, toAlpha);
        set.addListener(new TransitionAnimsListener() {
            @Override
            public void onAnimationEnd(Animator animator) {
                // TODO 自動生成的方法存根
                super.onAnimationEnd(animator);
                if (isEnter) {
                    enterAnimsEnd();
                }else {
                    exitAnimsEnd();
                }
            }
        });
        set.play(alphaAnim);
        set.setDuration(getAnimsDuration());
        set.setStartDelay(getAnimsStartDelay());
        set.setInterpolator(getAnimsInterpolator());
        set.start();
    }
    
    @Override
    public void playScreenEnterAnims() {
        // TODO 自動生成的方法存根
        playScreenAnims(true);
    }

    @Override
    public void playScreenExitAnims() {
        // TODO 自動生成的方法存根
        playScreenAnims(false);
    }

    
}

 設置方式:

TransitionCompat.setEnterTransition(new SceneFade(this, true));

@Override
public void onBackPressed() {

  TransitionCompat.setExitTransition(new SceneFade(this, true));
  // 這段代碼必須放在TransitionCompat各種設置之后
  TransitionCompat.finishAfterTransition(this);
}

 

五、小例子

MainActivity.java

package com.example.activityoptionsjbtest;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.Pair;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.kale.activityoptions.ActivityCompatICS;
import com.kale.activityoptions.ActivityOptionsCompatICS;


public class MainActivity extends ActionBarActivity {
    private ImageView chromeIView;
    private Intent intent;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        intent = new Intent(MainActivity.this, TargetActivity.class);
        chromeIView = (ImageView)findViewById(R.id.chrome_imageView);
        
    }
    public void buttonListener(View views) {
        switch (views.getId()) {
case R.id.thumbnail_button:
            thumbNailScaleAnim(chromeIView);
            break;default:
            break;
        }
    }public void thumbNailScaleAnim(ImageView view) {
        view.setDrawingCacheEnabled(true);
         Bitmap bitmap = view.getDrawingCache();
          ActivityOptionsCompatICS options = ActivityOptionsCompatICS.makeThumbnailScaleUpAnimation(
            view, bitmap, 0, 0);
          // Request the activity be started, using the custom animation options.
          ActivityCompatICS.startActivity(MainActivity.this, intent, options.toBundle());
          //view.setDrawingCacheEnabled(false);
    }
}

 

TargetActivity.java

package com.example.activityoptionsjbtest;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;

import com.kale.activityoptions.anim.SceneFade;
import com.kale.activityoptions.anim.ViewAnimationListenerAdapter;
import com.kale.activityoptions.transition.TransitionCompat;
import com.kale.activityoptions.transition.TransitionListenerAdapter;


public class TargetActivity extends Activity{

    boolean isShowed = false;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO 自動生成的方法存根
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_target);// 這段代碼必須放在TransitionCompatICS各種設置之后
        TransitionCompat.startTransition(this, R.layout.activity_target);
    }
    
    
    
    @Override
    public void onBackPressed() {
        //super.onBackPressed();// 這段代碼必須放在TransitionCompatICS各種設置之后
        TransitionCompat.finishAfterTransition(this);
        
    }
}

 

這個項目兼容到3.1,對於2.x我試着兼容了一部分,但還有幾個小問題。所以就只做了一個高版本的。畢竟目前4.x才是主流。

 

下載地址https://github.com/tianzhijiexian/ActivityOptionsICS


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM