Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 知識要點整理(12)----Animation(動畫)

Android 知識要點整理(12)----Animation(動畫)

編輯:關於Android編程

動畫分類

Android動畫有3類:幀動畫、視圖動畫、屬性動畫。幀動畫和視圖動畫又統稱為補間動畫。Android 3.0(API LEVEL 11)開始支持屬性動畫

幀動畫

幀動畫是針對Drawable資源的動畫。其本質是一系列Drawable資源的連續變化,其本質是AnimationDrawable對象。其使用方法如下:

定義AnimationDrawable

資源中用到了表示天氣的三張圖片


    
    
    

代碼

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        ImageView sampleIv= (ImageView)findViewById(R.id.iv_sample);
        sampleIv.setBackgroundResource(R.drawable.wether_list);
        final AnimationDrawable animationDrawable = (AnimationDrawable)sampleIv.getBackground();
        sampleIv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.start();
            }
        });

    }

效果圖

點擊圖片之後就會連續變換不同的圖片出來
這裡寫圖片描述

視圖動畫

視圖動畫是對視圖控件(View)應用動畫,其本質是連續修改View的屬性來展現變化。主要有Scale,Rotate,Translate,Alpha。使用方法如下:

定義動畫資源

旋轉動畫

透明度動畫


位移動畫



組合動畫


    

    
    
    

代碼

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        final ImageView sampleIv= (ImageView)findViewById(R.id.iv_sample);
        final Animation animation = AnimationUtils.loadAnimation(this,R.anim.roate360);
        animation.setDuration(1500);
        animation.setInterpolator(this,android.R.anim.linear_interpolator);
        animation.setRepeatCount(Animation.INFINITE);
        sampleIv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sampleIv.startAnimation(animation);
            }
        });

    }

效果圖

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

屬性動畫

接下來重點講屬性動畫。
屬性動畫不僅僅針對視圖(View),它幾乎可以應用到任何對象。你可以定義屬性動畫來改變任意對象的屬性,不管這個對象是否會在屏幕上呈現出來。屬性動畫的本質是在一定時間段內連續地改變對象的屬性。

屬性動畫和視圖動畫的區別

視圖動畫只能針對視圖對象應用動畫,而且視圖動畫只能針對視圖的部分應用動畫,例如可以縮放,旋轉,但是不能對視圖背景色應用動畫等等。 視圖動畫只會改變視圖繪制的位置,而不會改變視圖本身所在的位置。所以如果一個視圖通過視圖動畫移動到了另一位置,你點擊它的新位置並不會正確的響應點擊事件,而必須在原來的初始位置點擊才會有效果。 屬性動畫則完全沒有上邊的限制,可以使用屬性動畫作用在任何對象的任何屬性,不管它是視圖控件還是非視圖控件。並且,屬性動畫會真正的改變對象本身,事件都會在動畫後的位置上生效。 當然,使用視圖動畫的開銷比屬性動畫要低,我們可用用很少的步驟和很少的代碼去實現是視圖動畫效果。所以,如果視圖動畫可以達到目標,也沒必要一定要用屬性動畫。

簡單的例子

淡入淡出動畫
showView.setAlpha(0f);
showView.setVisibility(View.VISIBLE);

showView.animate()
         .alpha(1f)
         .setDuration(300/*ms*/)
         .setListener(null);

hideView.animate()
        .alpha(0f)
        .setDuration(mShortAnimationDuration)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                hideView.setVisibility(View.GONE);
            }
         });
效果圖

淡入淡出

翻轉動畫

下面展示如何在切換Fragmeng時應用翻轉動畫

java代碼
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_card_flip);

        if (savedInstanceState == null) {
            // 如果沒有實例,則將CardFrontFragment添加到Activity
            //否則表明之前已經添加Fragment了
            getFragmentManager()
                    .beginTransaction()
                    .add(R.id.container, new CardFrontFragment())
                    .commit();
        } else {
            mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
        }

        // 監控返回棧的變化,以便正確地顯示操作圖標
        getFragmentManager().addOnBackStackChangedListener(this);
    }

    @Override
    public void onBackStackChanged() {
        mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);

        // 當返回棧發生變化,更新菜單顯示
        invalidateOptionsMenu();
    }

private void flipCard() {
        //如果返回棧中有實例,直接返回當前一個Fragment
        if (mShowingBack) {
            getFragmentManager().popBackStack();
            return;
        }

        //指示可以返回上一個Fragment
        mShowingBack = true;

        //添加CarBackFragment

        getFragmentManager()
                .beginTransaction()

                // 自定義Frameng切換時的動畫
                //包括切換當當前Fragment和返回到上一個Fragment的動畫
                //這樣當按返回按鈕時也會有動畫效果
                .setCustomAnimations(
                        R.animator.card_flip_right_in/*enter*/, R.animator.card_flip_right_out/*exit*/,
                        R.animator.card_flip_left_in/*popEnter*/, R.animator.card_flip_left_out/*popExit*/)

                // 替換Fragment
                .replace(R.id.container, new CardBackFragment())

                // 將該事務添加到返回棧,這樣才能響應返回按鈕操作
                .addToBackStack(null)

                // 提交事務
                .commit();

        // 延遲更新菜單
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                invalidateOptionsMenu();
            }
        });
    }
動畫資源

car_flip_right_in.xml


    
    

card_flip_right_out.xml


    
    

card_flip_left_in.xmlcar_flip_right_in.xml差不多,只是rotationY動畫的起止角度 valueFrom=”-180”,valueTo=”0”.
card_flip_left_out.xmlcar_flip_right_out.xml差不多,只是rotationY動畫的起止角度 valueFrom=”0”,valueTo=”180”.

效果圖

這裡寫圖片描述

滑屏動畫

下面展示有何在ViewPager切換Page的時候應用動畫

java代碼

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_slide);

        //實例化ViewPager和PagerAdapter對象
        mPager = (ViewPager) findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
        mPager.setAdapter(mPagerAdapter);
        mPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                invalidateOptionsMenu();
            }
        });
    }

菜單操作

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            //...

            case R.id.action_zoom:
                //設置縮放動畫,在切換page的時候會看到效果
                mPager.setPageTransformer(false,new ZoomPageTransformer());
                return true;
            case R.id.action_depth:
                mPager.setPageTransformer(false,new DepthPageTransformer());
                return true;
            case R.id.action_default:
                //恢復默認動畫
                mPager.setPageTransformer(false,null);
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

DepthPageTransformer.java

public class DepthPageTransformer implements ViewPager.PageTransformer {
    @Override
    public void transformPage(View page, float position) {

        int pageWidth = page.getWidth();
        if(position <= -1){
            //當不在屏幕顯示范圍時,恢復所有屬性
            page.setAlpha(1);
            page.setTranslationX(0);
            page.setScaleX(1);
            page.setScaleY(1);
        }else if(position < 0){
            //屏幕左側page
            page.setTranslationX(-position*pageWidth);
            page.setScaleX(position*0.3f+1f);
            page.setScaleY(position*0.3f+1f);
            page.setAlpha(1+position*0.8f);
        }else if(position < 1) {
            //屏幕右側page
            page.setTranslationX(0);
            page.setScaleX(1);
            page.setScaleY(1);
            page.setAlpha(1);

        }else{
            //當不在屏幕顯示范圍時,恢復所有屬性
            page.setAlpha(1);
            page.setTranslationX(0);
            page.setScaleX(1);
            page.setScaleY(1);
        }
    }
}

ZoomPageTransformer.java

public class ZoomPageTransformer implements ViewPager.PageTransformer {
    @Override
    public void transformPage(View page, float position) {

        if(position <= -1){
            //當不在屏幕顯示范圍時,恢復所有屬性
            page.setScaleX(1);
            page.setScaleY(1);
            page.setTranslationX(0);
            page.setAlpha(1);
        }else if(position < 1){
            //在屏幕上顯示的page
            float pageWidth = page.getWidth();
            float pageHeight = page.getHeight();
            float scaleFactor = Math.max(0.85f,1 -Math.abs(position));
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
            page.setAlpha(scaleFactor);

            float verticalMargin = pageHeight*(1-scaleFactor)/2;
            float horizonMargin = pageWidth*(1-scaleFactor)/2;
            if(position < 0){
                page.setTranslationX(horizonMargin-verticalMargin/2);
            }else {
                page.setTranslationX(-horizonMargin+verticalMargin/2);
            }
        }else{
            //當不在屏幕顯示范圍時,恢復所有屬性
            page.setScaleX(1);
            page.setScaleY(1);
            page.setTranslationX(0);
            page.setAlpha(1);
        }

    }
}
效果圖

這裡寫圖片描述

縮放動畫

java代碼
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zoom);
        mImageRcv = (RecyclerView)findViewById(R.id.rcv_images);
        mAdapter = new ImageAdapter(this);
        mAdapter.setOnItemClickListener(new ImageAdapter.OnItemClickListener() {
            @Override
            public void onItemClicked(View view, int pos) {
                zoomImageFromThumb(view,mAdapter.getItemData(pos));
            }
        });
        mImageRcv.setAdapter(mAdapter);
        mImageRcv.setLayoutManager(new  GridLayoutManager(this,3,
                LinearLayoutManager.VERTICAL,false));

        mShortAnimationDuration = getResources()
        .getInteger(android.R.integer.config_shortAnimTime);
    }
    /**
     * 動畫執行關鍵代碼
     **/
    private void zoomImageFromThumb(final View thumbView, int imageResId) {
        // 取消上一個動畫
        if (mCurrentAnimator != null) {
            mCurrentAnimator.cancel();
        }

        // 加載高清圖片
        final ImageView expandedImageView = (ImageView) findViewById(R.id.expanded_image);
        expandedImageView.setImageResource(imageResId);

        // 計算尺寸,以便精准動畫
        final Rect startBounds = new Rect();
        final Rect finalBounds = new Rect();
        final Point globalOffset = new Point();

        // 獲取屏幕絕對坐標
        thumbView.getGlobalVisibleRect(startBounds);
        findViewById(R.id.container).getGlobalVisibleRect(finalBounds, globalOffset);
        startBounds.offset(-globalOffset.x, -globalOffset.y);
        finalBounds.offset(-globalOffset.x, -globalOffset.y);

        //
        float startScale;
        if ((float) finalBounds.width() / finalBounds.height()
                > (float) startBounds.width() / startBounds.height()) {
            startScale = (float) startBounds.height() / finalBounds.height();
        } else {
            startScale = (float) startBounds.width() / finalBounds.width();

        }

        //隱藏縮略圖並開始動畫顯示高清圖
        thumbView.setAlpha(0f);
        expandedImageView.setVisibility(View.VISIBLE);

        // 設置動畫的中心為坐標原點
        expandedImageView.setPivotX(0f);
        expandedImageView.setPivotY(0f);

        // 構造動畫
        AnimatorSet set = new AnimatorSet();
        set
                .play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left,
                        finalBounds.left))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top,
                        finalBounds.top))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f));
        set.setDuration(mShortAnimationDuration);
        set.setInterpolator(new DecelerateInterpolator());
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mCurrentAnimator = null;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                mCurrentAnimator = null;
            }
        });
        set.start();
        mCurrentAnimator = set;

        //再次點擊還原,逆過程
        final float startScaleFinal = startScale;
        expandedImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mCurrentAnimator != null) {
                    mCurrentAnimator.cancel();
                }

                AnimatorSet set = new AnimatorSet();
                set
                        .play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left))
                        .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top))
                        .with(ObjectAnimator
                                .ofFloat(expandedImageView, View.SCALE_X, startScaleFinal))
                        .with(ObjectAnimator
                                .ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal));
                set.setDuration(mShortAnimationDuration);
                set.setInterpolator(new DecelerateInterpolator());
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }
                });
                set.start();
                mCurrentAnimator = set;
            }
        });
    }
效果圖

這裡寫圖片描述


以上就是動畫相關的知識。

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