• 补间动画 帧动画 基本使用 案例 [MD]


    博文地址

    我的GitHub我的博客我的微信我的邮箱
    baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

    补间动画

    补间动画基本使用演示

    MainActivity

    public class MainActivity extends ListActivity {
        private ImageView iv;
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            String[] array = {"alpha",
                "trans",
                "scale",
                "rotate",
                "set",
                "fillAfter = true时,不管其他怎么设置,都是使用最后一帧",
                "fillAfter = false时,不管其他怎么设置,都是使用第一帧",};
            setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
            iv = new ImageView(this);
            iv.setBackgroundColor(0x330000ff);
            iv.setImageResource(R.drawable.icon);
            iv.setOnClickListener(v -> Toast.makeText(this, "点击了View", Toast.LENGTH_SHORT).show());
            getListView().addHeaderView(iv);
        }
    
        @Override
        protected void onListItemClick(ListView l, View view, int position, long id) {
            Animation animation = null;
            switch (position - getListView().getHeaderViewsCount()) {
                case 0:
                    animation = AnimHelper.alpha();
                    break;
                case 1:
                    animation = AnimHelper.trans();
                    break;
                case 2:
                    animation = AnimHelper.scale();
                    break;
                case 3:
                    animation = AnimHelper.rotate();
                    break;
                case 4:
                    animation = AnimHelper.set();
                    break;
                case 5:
                    animation = AnimHelper.scale();
                    animation.setFillEnabled(new Random().nextBoolean());
                    animation.setFillBefore(new Random().nextBoolean());
                    animation.setFillAfter(true);//动作结束后停留在最后一帧
                    break;
                case 6:
                    animation = AnimHelper.scale();
                    animation.setFillEnabled(new Random().nextBoolean());
                    animation.setFillBefore(new Random().nextBoolean());
                    animation.setFillAfter(false);//动作结束后停留在第一帧(没有进行任何缩放)
                    break;
            }
            iv.startAnimation(animation);
        }
    }

    AnimHelper

    public class AnimHelper {
    
        //透明度动画
        public static Animation alpha() {
            AlphaAnimation animation = new AlphaAnimation(1.0f, 0.1f);//开始、结束时的透明度。1为全不透明,0为全透明
            animation.setDuration(2000);//播放时间
            animation.setRepeatCount(1);//重复次数,默认为0。播放次数=重复次数+1。Animation.INFINITE表示不停止的播放
            animation.setRepeatMode(Animation.RESTART);//【REVERSE】倒序重复播放,【RESTART】重新开始执行(默认)
            animation.setInterpolator(new AccelerateInterpolator());//加速
            return animation;
        }
    
        //位移动画
        public static Animation trans() {
            TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f,//8个参数:fromXType, fromXValue, toXType, toXValue
                Animation.RELATIVE_TO_SELF, -1f, //【开始/结束】时【相对谁】的距离
                Animation.RELATIVE_TO_PARENT, 1f);
            animation.setDuration(1000);
            animation.setRepeatCount(Animation.INFINITE); //不停止的播放
            animation.setRepeatMode(Animation.REVERSE); //倒序重复播放
            animation.setInterpolator(new BounceInterpolator());//动画结束的时候弹起
            return animation;
        }
    
        //缩放动画
        public static Animation scale() {
            ScaleAnimation animation = new ScaleAnimation(0.5f, 2.5f, //开始、结束时x的缩放比例
                0.1f, 1.5f, //开始、结束时y的缩放比例
                Animation.RELATIVE_TO_SELF, 0.5f, //x缩放时所使用的模式和中心点
                Animation.RELATIVE_TO_SELF, 0.5f); //y缩放时所使用的模式和中心点
            animation.setDuration(1000);
            animation.setInterpolator(new AccelerateDecelerateInterpolator());//先加速后减速
            return animation;
        }
    
        //旋转动画
        public static Animation rotate() {
            RotateAnimation animation = new RotateAnimation(0, 360 * 5, //开始、结束时旋转角度
                Animation.RELATIVE_TO_SELF, 0.5f,  //x旋转时所使用的模式和中心点
                Animation.RELATIVE_TO_SELF, 0.5f); //y旋转时所使用的模式和中心点
            animation.setDuration(1000);
            animation.setInterpolator(new LinearInterpolator());//匀速
            return animation;
        }
    
        //组合动画
        public static AnimationSet set() {
            AnimationSet animationSet = new AnimationSet(false);//是否使用共同的插值器
            //位移
            TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.RELATIVE_TO_PARENT, 0.5f,
                Animation.RELATIVE_TO_PARENT, 0.5f);
            ta.setDuration(800);
            ta.setInterpolator(new AccelerateInterpolator());//快-慢
    
            //缩放
            ScaleAnimation sa = new ScaleAnimation(2f, 1f, 0.5f, 2f,
                Animation.RELATIVE_TO_PARENT, 0.5f,
                Animation.RELATIVE_TO_PARENT, 0.5f);
            sa.setDuration(800);
            sa.setStartOffset(1000);//延迟时间 When this Animation should start
    
            //旋转
            RotateAnimation ra = new RotateAnimation(0, 360 * 5,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
            ra.setDuration(1500);
            ra.setStartOffset(2000);
            sa.setInterpolator(new DecelerateInterpolator()); //慢-快
    
            //将上面这些动画放到集合中
            animationSet.addAnimation(ta);
            animationSet.addAnimation(sa);
            animationSet.addAnimation(ra);
            //set.setFillEnabled(true);
            animationSet.setFillAfter(true);
            //set.setFillBefore(false);
            return animationSet;
        }
    }

    几十种 Interpolator 演示

    public class SecondActivity extends ListActivity {
        int[] array_id = {R.anim.alpha_in, R.anim.disappear_bottom_right_in, R.anim.disappear_bottom_right_out,
            R.anim.disappear_top_left_in, R.anim.disappear_top_left_out, R.anim.drawroll_ani_in, R.anim.drawroll_ani_out,
            R.anim.fade_out, R.anim.flip_horizontal_in, R.anim.flip_horizontal_out, R.anim.flip_vertical_in, R.anim.flip_vertical_out,
            R.anim.gallery_in, R.anim.grow_from_top, R.anim.left_in, R.anim.left_out, R.anim.mi_laucher_alpha,
            R.anim.mi_laucher_del_done, R.anim.mi_laucher_del_down, R.anim.mi_laucher_out, R.anim.mi_laucher_scale_in,
            R.anim.mi_laucher_scale_out, R.anim.pophidden_anim, R.anim.popshow_anim, R.anim.push_left_in, R.anim.push_left_out,
            R.anim.push_up_in, R.anim.push_up_out, R.anim.rbm_in_from_left, R.anim.rbm_out_to_left, R.anim.refreshable_list_rotate,
            R.anim.right_in, R.anim.right_out, R.anim.shrink_from_bottom, R.anim.slide_down_out, R.anim.slide_left,
            R.anim.slide_right, R.anim.slide_up_in, R.anim.small_2_big, R.anim.umeng_fb_slide_in_from_left,
            R.anim.umeng_fb_slide_in_from_right, R.anim.umeng_fb_slide_out_from_left, R.anim.umeng_fb_slide_out_from_right,
            R.anim.umeng_socialize_fade_in, R.anim.umeng_socialize_fade_out, R.anim.umeng_socialize_shareboard_animation_in,
            R.anim.umeng_socialize_shareboard_animation_out, R.anim.umeng_socialize_slide_in_from_bottom,
            R.anim.umeng_socialize_slide_out_from_bottom, R.anim.unzoom_in, R.anim.unzoom_out, R.anim.welcome_fade_in_scale,
            R.anim.welcome_fade_out, R.anim.zoom_enter, R.anim.zoom_exit};
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            String[] array_name = new String[array_id.length];
            for (int i = 0; i < array_id.length; i++) {
                String name = getResources().getResourceName(array_id[i]);
                array_name[i] = name.replace(getPackageName() + ":anim/", "");
            }
            setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array_name));
    
            getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view, int scrollState) {
                    Log.i("bqt", "【onScrollStateChanged】" + scrollState); //卧槽,我发现滑动时这个方法并不一定会回调
                    // AbsListView.OnScrollListener.SCROLL_STATE_FLING; //屏幕处于甩动状态
                    // AbsListView.OnScrollListener.SCROLL_STATE_IDLE; //停止滑动状态
                    // AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL;// 手指接触状态
                    if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                        int visibleCount = getListView().getLastVisiblePosition() - getListView().getFirstVisiblePosition() + 1; //可见的数量
                        for (int i = 0; i < visibleCount; i++) {
                            int reallyIndex = i + getListView().getFirstVisiblePosition();//真正的位置
                            int alpha = 255 * reallyIndex / view.getCount();
                            int color;
                            if (reallyIndex % 2 == 0) color = Color.argb(alpha, 0, 255, 0);
                            else color = Color.argb(alpha, 0, 0, 255);
                            getListView().getChildAt(i).setBackgroundColor(color);
                        }
                    }
                }
    
                @Override
                public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                    //当前窗口中能看见的第一个列表项ID,当前窗口中能看见的列表项的个数,列表项的总数
                    //Log.i("bqt", "【onScroll】" + firstVisibleItem + "," + visibleItemCount + "," + totalItemCount);
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.i("bqt", "【onResume】");
        }
    
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            v.setAnimation(AnimationUtils.loadAnimation(this, array_id[position]));
        }
    }

    自定义 Activity 转场动画

    默认转场动画

    • 淡入淡出效果:overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);
    • 由左向右滑入的效果:overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);

    自定义转场动画

    public class BaseActivity extends Activity {
        @Override
        public void startActivity(Intent intent) {
            super.startActivity(intent);
            overridePendingTransition(R.anim.activity_in_from_down, R.anim.activity_out_to_up);
        }
    
        @Override
        public void finish() {
            super.finish();
            overridePendingTransition(R.anim.activity_in_from_top, R.anim.activity_out_to_down);
        }
    }
    public class Activity1 extends BaseActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(R.drawable.icon);
            imageView.setBackgroundColor(0xFF000000 + new Random().nextInt(0xFFFFFF));
            imageView.setOnClickListener(v -> startActivity(new Intent(this, Activity1.class)));
            setContentView(imageView);
        }
    }

    系统定义的几个补间动画

    存放位置:android_sdkplatformsandroid-28data esanim 
    默认时间:<integer name="config_mediumAnimTime">400</integer>

    fade_in 淡入

    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="@android:integer/config_longAnimTime"
           android:fromAlpha="0.0"
           android:interpolator="@interpolator/decelerate_quad"
           android:toAlpha="1.0"/>

    fade_out 淡出

    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="@android:integer/config_mediumAnimTime"
           android:fromAlpha="1.0"
           android:interpolator="@interpolator/accelerate_quad"
           android:toAlpha="0.0"/>

    slide_out_right 淡出到右边屏幕

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromXDelta="0"
            android:toXDelta="50%p"/>
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="1.0"
            android:toAlpha="0.0"/>
    </set>

    slide_out_left

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromXDelta="0"
            android:toXDelta="-50%p"/>
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="1.0"
            android:toAlpha="0.0"/>
    </set>

    slide_in_right

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromXDelta="50%p"
            android:toXDelta="0"/>
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"/>
    </set>

    slide_in_left 从左边淡入到屏幕

    <set xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://schemas.android.com/apk/res/android ">
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromXDelta="-50%p"
            android:toXDelta="0"/>
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"/>
    </set>

    slide_in_child_bottom

    <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@interpolator/decelerate_quad">
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromYDelta="100%"
            android:toYDelta="0"/>
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"/>
    </set>

    常用的窗口显示、消失动画

    通过下面代码可以实现在Dialog或AlertDialog显示、消失时的具有可爱的动画效果:

    dialog.getWindow().setWindowAnimations(R.style.dialog_anim);

    通过下面代码可以实现在popupWindow 显示、消失时的具有可爱的动画效果:

    popWindow.setAnimationStyle(R.style.dialog_anim);

    其中,R.style.dialog_anim为在styles.xml中定义的一个样式:

     <style name="dialog_animation" parent="@android:style/Animation">
        <!--窗体进入动画--><item name="android:windowEnterAnimation">@anim/popshow_anim</item>
        <!--窗体退出动画--><item name="android:windowExitAnimation">@anim/pophidden_anim</item>
    </style>

    其中引用的便是两个自定义的补间动画,常用的效果的设置如下:

    popshow_anim.xml 由下往上淡入

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android" >
        <translate
            android:duration="1000"
            android:fromYDelta="100%p"
            android:toYDelta="0" />
        <alpha
            android:duration="1000"
            android:fromAlpha="0.0"
            android:toAlpha="1.0" />
    </set>

    pophidden_anim.xml 由上往下淡出

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android" >
        <translate
            android:duration="1000"
            android:fromYDelta="0"
            android:toYDelta="50%p" />
        <alpha
            android:duration="1000"
            android:fromAlpha="1.0"
            android:toAlpha="0.0" />
    </set>

    帧动画

    基本使用案例

    1、在res/drawable/目录下定义动画:

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                    android:oneshot="true">
        <item
            android:drawable="@drawable/icon"
            android:duration="200"/>
        <item
            android:drawable="@drawable/ic_launcher"
            android:duration="200"/>
        <item
            android:drawable="@drawable/pic"
            android:duration="200"/>
    </animation-list>

    2、设置为背景

    view.setBackgroundResource(R.drawable.frame_anim); //必须设为背景

    3、开启动画

    Drawable drawable = view.getBackground();
    if (drawable instanceof AnimationDrawable) {
        AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
        Toast.makeText(this, "是否正在运行:" + animationDrawable.isRunning(), Toast.LENGTH_SHORT).show();
        animationDrawable.stop();
        animationDrawable.start();
    }

    注意事项: 
    It's important to note that the start() method called on the AnimationDrawable cannot be called during the onCreate() method of your Activity, because the AnimationDrawable is not yet fully attached to the window. If you want to play the animation immediately, without requiring interaction, then you might want to call it from the onWindowFocusChanged() method in your Activity, which will get called when Android brings your window into focus.

    请注意,在Activity的onCreate()方法中,不能调用AnimationDrawable的start()方法,因为AnimationDrawable尚未完全附加到窗口。如果要立即播放动画,而不需要交互,那么您可能希望在Activity中的onWindowFocusChanged()方法中调用它,当Android将您的窗口置于焦点时,该动画将被调用。

    帧动画简介

    Drawable Animation 或者 Frame Animation,帧动画,就像GIF图片(或电影)一样,是通过依次显示一系列的 Drawable 来模拟动画的效果。

    <animation-list>为根元素,一个<item>表示一帧要轮换显示的图片

    • oneshot 代表着是否只展示一遍,设置为false会不停的循环播放动画
    • duration 属性表示此帧显示的时间

    注意事项:

    • 帧动画是指背景动画,所以只能设置 background 属性为指定的帧动画,或在代码中通过 setBackgroundResource(R.drawable.amin_id) 指定帧动画,但是不能设置 src 属性为指定的帧动画。当然两者可以同时设置,此时src保持不变,背景是个动画会改变。
    • 开启或关闭帧动画前最好先判断获取的帧动画是否为空,因为帧动画是通过 getBackground() 强转过来的,可能不存在!
    • 最重要的:不要在onCreate()中调用start方法开启帧动画,因为此时帧动画还没有完全跟Window相关联,如果想要在界面显示时就立即开始动画的话,可以在onWindowFoucsChanged()方法中调用start方法。

    虽然定义三种动画的xml文件都可以放置在res/anim/文件夹中,但是建议:

    • 帧动画放在res/drawable文件夹中
    • 补间动画放在res/anim文件夹中
    • 属性动画放在res/animator文件夹中

    AnimationDrawable 类简介

    public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable

    AnimationDrawable 是 Drawable 的间接子类。

    Drawable 相关的方法:

    • void addFrame(Drawable frame, int duration):Adds a frame to the animation
    • Drawable getFrame(int index):Return the Drawable at the specified frame index
    • Drawable mutate():Make this drawable mutable易变的. This operation cannot be reversed反转.

    动画相关的方法:

    • int getDuration(int i):Return the duration in milliseconds of the frame at the specified index
    • int getNumberOfFrames():Return the number of frames in the animation
    • boolean isOneShot():Return true of the animation will play once, false otherwise
    • void setOneShot(boolean oneShot):Sets whether the animation should play once or repeat.

    其他不常用的方法:

    • void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Resources.Theme theme):Inflate this Drawable from an XML resource optionally styled by a theme.
    • void run():This method exists for implementation purpose only and should not be called directly. Invoke start() instead.
    • boolean setVisible(boolean visible, boolean restart):Sets whether this AnimationDrawable is visible.
    • void unscheduleSelf(Runnable what):Use the current Drawable.Callback implementation to have this Drawable unscheduled.

    最常用的是 Animatable 接口中定义的三个方法:

    public interface Animatable {
        void start(); //Starts the drawable's animation. This method has no effect if the animation is running.
        void stop(); //Stops the drawable's animation. This method has no effect if the animation is not running.
        boolean isRunning(); //Indicates whether the animation is running.
    }

    2016-11-04

  • 相关阅读:
    练习!!标准体重
    C# 阶乘累加
    C# 阶乘
    C# 累加求和
    C# 100块钱,买2元一只的圆珠笔3块钱一个的尺子5元一个的铅笔盒每样至少一个,正好花光,有多少种花法。
    C# 一张纸0.00007m,折多少次和珠峰一样高
    C# 100以内质数
    C# 100以内质数和
    网站的基本布局
    C#递归
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/6031260.html
Copyright © 2020-2023  润新知