Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android動畫之視圖動畫

Android動畫之視圖動畫

編輯:關於Android編程

前言

動畫在Android中是一個相當於重要的知識點,使用場景也很多,炫酷的界面效果少不了動畫來提升,這裡我們就先來說說Android中的動畫,在說Android的動畫之前,我們先來了解一下動畫這個效果的通用含義。

什麼是動畫?

我們在平常生活中,經常會遇到動畫這個詞,大家也不要想歪了,可不是大家理解的島國xx片哦!,那動畫究竟是什麼吶?在不同的場景中,這個詞的名詞解釋都不一樣,那我們這裡也來討論一下動畫是什麼?

1,動畫就是動起來的畫
2,動畫最基本的一點就是能夠隨一定的時間間隔而變化

這個定義也是我總結的,感覺還挺契合這個概念,如果大家有異議,請告訴我,反正我也不會改的。

動畫屬性

動畫的概念已經有了,那通用的動畫有哪些屬性吶,或者說具備哪些屬性,比如我有如下一個動畫:

從這個動畫我們能夠得出哪些屬性?

描述 結論 作用的對象 traget 持續時間 duration 從哪兒來 from 到哪兒去 to 開始時間 beginTime 重復次數 repeatCount 怎麼去 timeLine

上面我大致總結了一下公共的屬性,這些屬性針對任何動畫都適用,可能還總結的不夠全,這裡只是起到一個拋磚引玉的作用。

動畫組合

定義有了,屬性有了,還有啥公共是屬性?那就是動畫的執行效果了,一般有單個動畫,就是一次只執行一個動畫,還有就是組合動畫了,多個動畫可以組合成,串行,並行,串並行動畫。

對公共的動畫我們大致就先說這麼多,現在開始轉移到我們的主題內容,Android動畫。接下的我們就來說說在Android中的動畫的一些概念和怎麼使用!

Android中的動畫分類

視圖動畫
Tween動畫
平移動畫 旋轉動畫 縮放動畫 漸變動畫 Frame動畫
AnimationDrawable 屬性動畫

視圖動畫

到這裡,我們終於今天本章的主題了。這裡主要來首先來說說視圖動畫,在下一章中我們會說說屬性動畫。視圖動畫與屬性動畫都同屬於Android,但是實現方式是完全不同的。

注意:視圖動畫只能作用於View,能夠實現的效果也僅限於上述的幾種和他們動畫的組合。

Android中的屬性對應關系

前面我們總結了動畫的通用屬性,那我們這裡就來看看Android中這些屬性的對應關系:

描述 結論 Android屬性 作用的對象 traget View 持續時間 duration duration 從哪兒來 from fromXXX 到哪兒去 to toXXX 開始時間 beginTime startOffset 重復次數 repeatCount repeactCount 怎麼去 timeLine interpolator

我們可以看到在Android中,屬性對應的名稱大致跟通用的總結的一致,至少看到名字就能理解意思。因此我們後面在實現動畫的時候就按照這些屬性來配置就ok了。

Tween動畫的結構

Animation
AlphaAnimation TranslateAnimation RotateAnimation ScaleAnimation AnimationSet
這裡前四個是單個動畫,後面一個是動畫集,他可以組合前面的動畫。

Android動畫實現

視圖動畫主要有兩種方式來實現:

1,xml實現,首先在res/anim目錄下定義動畫的xml文件,之後帶代碼中用AnimationUtils.loadAnimation()加載
2, 代碼實現,直接new對應的動畫實例來實現動畫。

我們來看幾個動畫效果,之後實例進行操作一遍:
這裡寫圖片描述

xml實現

在res/anim下定義動畫文件,我們分別定義漸變,平移,旋轉,縮放四個動畫文件:

漸變動畫,名稱為alpha.xml



fromAlpha表示動畫開始的透明度,toAlpha表示動畫結束的透明度,1.0表示完全不透明,0.0便是完全透明,兩個都是浮點數,duration便是動畫的持續時間,單位為毫秒,2000毫秒表示2秒。startOffset表示動畫開始的延遲時間,點擊開始1秒後開始執行,單位也是毫秒。

平移動畫,名稱為translate.xml




fromXDelta,fromYDelta表示動畫開始時的x,y坐標,toXDelta,toYDelta動畫結束的x,y坐標,這裡需要注意的是他可以設置三種類型的值,比如我們設置50:

50: 表示50個像素,是絕對值
50%: 表示自身大小一半,記住這裡是可以設置%號的,他等於0.5,如果設置0.5表示絕對值0.5
50%p :表示父元素大小的一半,p表示相對於父元素

縮放動畫,名稱為scale.xml




fromXScale,fromXScale動畫開始時x,y的縮放大小,toXScale,toXScale:動畫結束的x,y縮放大小,1表示本身大小,數值越大,縮放比例越大,pivotX,piovtY:縮放的中心坐標位置,可以設置值與平移動畫可以設置的類似:

50: 表示50個像素,是絕對值
50%: 表示自身中心位置
50%p :表示父元素的中心位置,p表示相對於父元素

旋轉動畫,名稱為rotate.xml




fromDegrees動畫開始的角度,toDegress動畫結束的角度,正數為順時針,負數為逆時針,pivotX,piovtY:旋轉的中心坐標位置,設置的方式與縮放相似。

xml文件定義好後,我們就需要在代碼中進行使用,可以先定義一個view,之後在界面中find出來,之後對view設置動畫:

private void rotate() {
    Animation rotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
    imageView.startAnimation(rotate);
}

private void scale() {
    Animation scale = AnimationUtils.loadAnimation(this, R.anim.scale);
    imageView.startAnimation(scale);
}

private void translate() {
    Animation translate = AnimationUtils.loadAnimation(this, R.anim.translate);
    imageView.startAnimation(translate);
}

private void alpha() {
    Animation alpha = AnimationUtils.loadAnimation(this, R.anim.alpha);
    imageView.startAnimation(alpha);
}

在代碼中,都需要先load動畫,采用AnimationUtils來進行load,之後將load出來的動畫設置到view上就可以了。

代碼實現

上面我們采用xml實現四種動畫,接下來我們用代碼來實現這個四種動畫:

private void rotate() {
    RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
    rotate.setDuration(3000);
    imageView.startAnimation(rotate);
}

private void scale() {
    ScaleAnimation scale = new ScaleAnimation(1,2, 1, 2, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
    scale.setDuration(3000);
    imageView.startAnimation(scale);
}

private void translate() {
    TranslateAnimation translate = new TranslateAnimation(0, 200, 0, 0);
    translate.setDuration(3000);
    imageView.startAnimation(translate);
}

private void alpha() {
    AlphaAnimation alpha = new AlphaAnimation(1.0f, 0.0f);
    alpha.setDuration(3000);
    imageView.startAnimation(alpha);
}

從代碼可以看出,四種動畫都分別對應了不同的類,已經有四種現場的動畫類可以使用。每次使用只需要new對應的實例,設置不同的參數,參數設置也很簡單。這裡就不在詳細說了。

動畫的開始於結束

動畫我們已經實現了,但是如果你需要在動畫的執行過程中,做某些操作怎麼辦吶?比如在動畫開始的時候提示一下動畫的開始,在動畫的結束時,我們提示動畫的結束,這我們又能怎麼做吶?

系統也完全考慮到這個問題,我們可以對動畫設置監聽,可以對動畫設置AnimationListener,如下:

rotate.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //todo
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // todo  next anim
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

設置動畫監聽,在動畫開始結束等時機,系統都會回調對應的函數,比如onAnimationStart就是告訴動畫開始執行了。這樣我們就可以根據不同的回調做想要做的事情。

組合動畫

我們在抽象動畫的公共屬性說過,動畫有單個動畫,還有組合動畫,上面我們所實現的都是單個動畫,那怎麼實現組合動畫,組合動畫又分為串行動畫,並行動畫,或者既有串行又有並行。這些又怎麼實現:

多個單個動畫來實現
串行動畫,可以定義多個動畫,分別對每一個動畫設置監聽,在上一個動畫結束時,開始下一個動畫,也可以設置動畫的startOffset,下一個動畫的startOffset為上一個動畫的startOffset與duration之和 並行動畫,定義多個動畫,設置同樣的startOffset與duration
采用AnimationSet來實現,下面我們主要才實現一下該方式

我們需要實現如下效果的動畫,由於將MP4轉換成gif,效果變得很差,將就著看吧:
這裡寫圖片描述vcq9yrXP1qOseG1syrXP1tPrtPrC68q1z9ajrNXiwO/N8rHksrvA68bk19qjrNa7sru5/crHvavJz8PmtcS1pbj2tq+7rbCy17DQ6NKqtcTQp7n71+m6z9K7z8K+zW9ro6zPwsPmztLDx9PDeG1swLTKtc/W0rvPwrjDtq+7raO6PC9wPg0KPHA+tqjS5dK7uPZsb3ZlX2ZsYXkueG1sPC9wPg0KPHByZSBjbGFzcz0="brush:java;">

代碼加載上面的定義的xml。

private void loveAnim() {
    Animation animation  = AnimationUtils.loadAnimation(this, R.anim.love_fly);
    love.startAnimation(animation);
}

這樣我們就實現了上面要求的效果,那代碼方式又怎麼實現? 首先定義多個單個動畫,之後采用AnimationSet來實現,將定義的動畫都add到set中,比如我們需要實現一個在平移的過程中放大並且逐漸消失的動畫:

private void alpha() {
    AlphaAnimation alpha = new AlphaAnimation(1.0f, 0.0f);
    alpha.setDuration(3000);

    TranslateAnimation translate = new TranslateAnimation(0, 200, 0, 0);
    translate.setDuration(3000);

    ScaleAnimation scale = new ScaleAnimation(1,2, 1, 2, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
    scale.setDuration(3000);

    AnimationSet set = new AnimationSet(true);
    set.addAnimation(alpha);
    set.addAnimation(translate);
    set.addAnimation(alpha);
    imageView.startAnimation(set);
}

new AnimationSet(true),true表示是否公用插值器,後面我們會詳細說說插值器。

這裡我們就已經說完了怎麼實現組合動畫,之後我們來講講插值器是個啥!

插值器

說道插值器,我們首先要知道插值器是干什麼用的?

插值器控制動畫在時間軸上的變換效果
我們先來幾個效果:
這裡寫圖片描述

我們分別就這幾個效果來做一下說明系統到底是怎麼來控制效果的,首先我們來看看AccelerateDecelerateInterpolator,該插值器是先加速後減速。

插值器中主要是根據getInterpolation來獲取某一個時間點的值,AccelerateDecelerateInterpolator的調用函數為(float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; 輸入范圍為0到1,根據這個函數我們可以生產如下的圖片:

這裡寫圖片描述

從函數圖可以看出,當輸入在0到1中時,函數先加速後減速,系統就是靠這個來控制動畫的執行效果的。

我們在來看CycleInterpolator,該插值器有一個震蕩的效果,我們來看看他的調用函數:(float)(Math.sin(2 * mCycles * Math.PI * input)); mCycles = 2, input( 0, 1),mCycles為2表示震蕩兩次,我們來看看函數圖:
這裡寫圖片描述

可以看到在0到1中循環了兩次。

從上面的可以看到如果你想實現特定的效果,只需要實現特定的插值器就好了。

動畫的最終位置

上面我們執行了多個動畫,都發現每次執行完成後都回到了初始位置,那我們怎麼才能將動畫停止在最終位置?其實很容易實現該效果,只需要設置動畫的setFillAfter為true就可以了。

動畫的響應

我們對動畫設置點擊事件,代碼如下:

public class LocationActivity extends AppCompatActivity {

    private ImageView love;

    public static void start(Context context) {
        Intent intent = new Intent();
        intent.setClass(context, LocationActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        findViews();
        setViewListener();
    }

    private void findViews() {
        love = (ImageView) findViewById(R.id.love);
        love.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(LocationActivity.this, "clicked", Toast.LENGTH_LONG).show();
            }
        });
    }

    private void setViewListener() {
        findViewById(R.id.set).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loveAnim();
            }
        });
    }

    private void loveAnim() {
        TranslateAnimation translate = new TranslateAnimation(0,0,0,-200);
        translate.setDuration(3000);
        translate.setFillAfter(true);
        love.startAnimation(translate);
    }
}

執行後,發現動畫在最終位置不能點擊,而點擊事件還是在初始位置。

視圖動畫是不可交互動畫,點擊事件還是在初始位置

幀動畫

我們來看看如下效果:
這裡寫圖片描述
首先我們需要定義一個動畫文件,但是該動畫文件不是放在res/anim下,而是放置drawable下面。
定義一個play_list.xml:



    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

之後在代碼中進行加載:

public class FrameActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView frame;
    private AnimationDrawable drawable;

    public static void start(Context context) {
        Intent intent = new Intent();
        intent.setClass(context, FrameActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frame);
        findViews();
        setViewsListener();
    }

    private void findViews() {
        frame = (ImageView) findViewById(R.id.frame);
    }

    private void setViewsListener() {
        findViewById(R.id.start).setOnClickListener(this);
        findViewById(R.id.end).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start:
                startAnim();
                break;
            case R.id.end:
                stopAnim();
                break;
        }
    }

    private void stopAnim() {
        if(drawable!=null){
            if(drawable.isRunning()){
                drawable.stop();
            }
        }
    }

    private void startAnim() {
        if(drawable==null){
            frame.setBackgroundResource(R.drawable.play_list);
            drawable = (AnimationDrawable) frame.getBackground();
            drawable.setOneShot(true);
        }
        if(!drawable.isRunning()){
            drawable.start();
        }
    }
}

將動畫文件設置為view的背景,之後在獲取出來為AnimationDrawable,setOneShot如果為true,表示只執行一次,start開始執行動畫,isRunning表示動畫知否在執行,stop停止動畫。其他屬性就不一一解釋了。

總結

到此視圖動畫就講述完了,下一章來說說屬性動畫。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved