Android 知识要点整理(12)----Animation(动画)

动画分类

Android动画有3类:帧动画、视图动画、属性动画。帧动画和视图动画又统称为补间动画。Android 3.0(API LEVEL 11)开始支持属性动画

帧动画

帧动画是针对Drawable资源的动画。其本质是一系列Drawable资源的连续变化,其本质是AnimationDrawable对象。其使用方法如下:

定义AnimationDrawable

资源中用到了表示天气的三张图片

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                android:oneshot="false">
    <item android:drawable="@mipmap/ic_sunny" android:duration="200" />
    <item android:drawable="@mipmap/ic_slight_drizzle" android:duration="200" />
    <item android:drawable="@mipmap/ic_haze" android:duration="200" />
</animation-list>

代码

 @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。使用方法如下:

定义动画资源

旋转动画

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
     android:fromDegrees="0"
            android:toDegrees="360"
            android:pivotX="50%"
            android:pivotY="50%"
 />

透明度动画

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1">
</alpha>

位移动画

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-100%"
    android:toXDelta="0"
    android:fromYDelta="-20%"
    android:toYDelta="0">

</translate>

组合动画

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:fromAlpha="0.2"
        android:toAlpha="1">

    </alpha>
    <scale
        android:fromXScale="0%"
        android:fromYScale="0%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="100%"
        android:toYScale="100%"/>
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360"
        />
</set>

代码

@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

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 在旋转动画之前,立刻将apha 设为0,注意duration=0 -->
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:duration="0" />

    <!-- 旋转动画 -->
    <objectAnimator
        android:valueFrom="180"
        android:valueTo="0"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="300" />

    <!-- 在旋转动画执行到二分之一的时候,立刻将alpha设为1,使之可见,注意 startOffset = 150. -->
    <objectAnimator
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:propertyName="alpha"
        android:startOffset="150"
        android:duration="1" />
</set>

card_flip_right_out.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 旋转 -->
    <objectAnimator
        android:valueFrom="0"
        android:valueTo="-180"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="@integer/card_flip_time_full" />

    <!-- 旋转一半的时候设置透明度为1,使之可见. -->
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:startOffset="@integer/card_flip_time_half"
        android:duration="1" />
</set>

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;
            }
        });
    }
效果图



以上就是动画相关的知识。

时间: 2024-10-12 20:04:39

Android 知识要点整理(12)----Animation(动画)的相关文章

Android 知识要点整理(11)----Scenes and Transitions(场景和变换)

除了常规的动画(帧动画.补间动画.属性动画)等作用于单个控件的动画,Android 还提供了一种类似的动画的功能,用于在两个不同的布局切换时提供过渡动画效果--Transitions Framework. Transitions Framework 简介 该框架帮助在布局改变的时候增加动画效果,它会在布局发生改变的时候应用一个或多个动画效果于布局中的每个控件.框架具有以下特点: 分组动画 一个或多个动画会作用于每个控件 基于变化的动画 动画是基于初始状态和最终状态的控件的属性值执行的 内置动画

android通过xml文件实现Animation动画

Rotate的xml文件编写方法 <rotate android:fromDegrees="0" android:toDegrees="+350" android:pivotX="50%" android:pivotY="50%" android:duration="1000"/> *android:toDegrees="+350"正号代表的是旋转方向,正号为顺时针,负号为逆

知识要点整理

extjs 以及 serverless api突破 extjs是基础 java python可以写serverless api java可以理解webbuilder 解析器,李金良要推进xwl2html抽离, 等李金良完成java 版本xwl2html,郭廷涛完成python xwl2html 李金良 郭丰 王占兴 郭庭涛 都要掌握extjs 李金良 郭丰 王占兴 郭庭涛都要掌握编写serverless api,语言java python php ruby go 没有任何限制,自己选择 java

Android Animation动画的xml使用

在Android应用程序,使用动画效果,能带给用户更好的感觉,做动画可以通过XML或Android代码来实现. Animation动画效果的实现可以通过两种方式进行实现,一种是tweened animation (渐变动画),另一种是frame by frame animation (画面转换动画). tweened animation渐变动画有以下两种类型: 1.alpha     渐变透明度动画效果 2.scale    渐变尺寸伸缩动画效果 frame by frame animation

Android Animation 动画学习笔记

最近两天学了android 动画方面的知识,从一点不懂到自己研究确实有收获. Animation 分为: <alpha  /> 透明度渐变 <scale  /> 尺寸渐变 <translate  /> 位移动画 <rotate  /> 旋转动画       在XML 和在JavaCode中都可以定义,方法分别为 XML中 javaCode中 <alpha  /> AlphAnimation <scale  /> ScaleAnimat

Android Animation (动画设计)

Android Animation(动画设计) 本文主要介绍逐帧动画,补间动画,属性动画 使用简单的图片 1.Bitmap和BitmapFactory 把一个Bitmap包装成BitmapDrawable对象,调用BitmapDrawable的构造器 BitmapDrawable drawable = new BitmapDrawable(bitmap); 获取BitmapDrawable所包装的Bitmap, Bitmap bitmap = drawable.getBitmap(); 2.Bi

Android Animation 动画Demo(Frame逐帧动画)

上一篇介绍了Animation动画其一:Tween补间动画. 这篇文章接下来介绍Animation另一种动画形式:Frame逐帧动画. Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画.Frame动画可以被定义在XML文件中,也可以完全编码实现(后面会给出这两种实现方式的源代码Demo). 下面分别介绍: 一.定义在xml中实现: 实现效果图: 源代码: 布局文件:main.xml: <?xml version="1.0" encodin

Android Animation动画(很详细)

http://www.360doc.com/content/13/0102/22/6541311_257754535.shtml Android Animation动画(很详细),布布扣,bubuko.com

Android学习——Animation动画效果

1.Android动画模式: 1>tweened animation: 渐变动画: 2>frame by frame: 画面转换动画. 2.Android的Animation动画由四种类型组成: XML alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 Java代码 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimat