Android 自定义动画 LoadingView

项目地址:https://github.com/CuteWiseCode/LoadingView

先上效果图

​​​


实现思路: 代码实现主要结合自定义view 以及动画属性的方式,根据需求调整动画的展示方式、加速度等。

一、动画的布局文件

      将白色背景图以及需要转动的图片资源引用到布局文件中。布局文件以FrameLayout 作为父view,默认展示背景图以及第一个转动的图片。


   android:layout_width="fill_parent"

   android:layout_height="fill_parent"

    android:layout_gravity="center"  >


       android:layout_gravity="center"

       android:layout_width="86.0dip"

       android:layout_height="86.0dip"

       android:background="@mipmap/bg_animation" />


       android:layout_gravity="center"

       android:id="@+id/loading_view_01"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       android:src="@mipmap/loading_01" />


        android:layout_gravity="center"

       android:id="@+id/loading_view_02"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       android:src="@mipmap/loading_02"

       android:visibility="invisible" />


       android:layout_gravity="center"

       android:id="@+id/loading_view_03"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       android:src="@mipmap/loading_03"

       android:visibility="invisible" />


       android:layout_gravity="center"

       android:id="@+id/loading_view_04"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       android:src="@mipmap/loading_04"

       android:visibility="invisible" />


       android:layout_gravity="center"

       android:id="@+id/loading_view_05"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:src="@mipmap/loading_05"

       android:visibility="invisible" />


二、创建一个 AnimationView 类

2.1、继承 FrameLayout ,重写两个构造函数   AnimationView(Context paramContext) 和 AnimationView(@NonNull Context context, @Nullable AttributeSet

attrs) ,了解自定义View的童鞋 应该知道,第一个构造函数用于在代码中新建时调用,第二个构造函数用户在布局文件中定义时调用。

        //构造函数

          public AnimationView(Context paramContext)

          {

            super(paramContext);

            inflate(getContext(),R.layout.loading_view, this);//layout_loading_view

            initializeView();

          }


        public AnimationView(@NonNullContext context, @Nullable AttributeSet attrs) {

               super(context,attrs);

               inflate(getContext(),R.layout.loading_view, this);//layout_loading_view

               initializeView();

        }

2.2、在构造函数中解析布局文件,并进行初始化

/**   *初始化控件

         */

          private void initializeView()

          {

            this.viewf =((ImageView)findViewById(R.id.loading_view_01));

            this.viewg =((ImageView)findViewById(R.id.loading_view_02));

            this.viewh =((ImageView)findViewById(R.id.loading_view_03));

            this.viewi =((ImageView)findViewById(R.id.loading_view_04));

            this.viewj =((ImageView)findViewById(R.id.loading_view_05));

            this.viewe = this.viewf;

            //测量控件的大小UNSPECIFIED = 0 EXACTLY = 1 AT_MOST= 2

            int m = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);

            int n = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);

            this.viewf.measure(m, n);

            this.floata = (this.viewf.getMeasuredWidth()/ 2);//获取宽的值,除2

            this.floatb = (this.viewf.getMeasuredHeight()/ 2);//获取高的值除2

            initView();//开始动画

          }


2.3、设置并开始动画,注意这里使用到动画监听animationListener

 public void initView()

          {

            tostartAnimation(this.viewe, 0.0F, 90.0F);

          }

/**

         * @param paramView具体某个view

         * @param paramFloat1 0.0f

         * @param paramFloat2 90.0f

         */

          private void tostartAnimation(View paramView,float paramFloat1, float paramFloat2)

          {


            AnimationLoad animation = newAnimationLoad(paramFloat1, paramFloat2, this.floata, this.floatb, this.floatc, true);

            animation.setDuration(this.intk);

            animation.setFillAfter(true);//true if theanimation should apply its transformation after it ends

            animation.setInterpolator(newAccelerateInterpolator());//Sets the acceleration curve for this animation.Defaults to a linear interpolation.Parameters:i The interpolator which definesthe acceleration curve

            animation.setAnimationListener(new animationListener());//theanimation listener to be notified

            paramView.startAnimation(animation);

          }

监听类:animationListener。在动画结束的时候,启动runnable,启动另一个动画

 private final classanimationListener

            implements Animation.AnimationListener

          {

            private animationListener()

            {

            }


            public void onAnimationEnd(AnimationparamAnimation)

            {

               //The Runnable that will be executed.

              AnimationView.this.post(new runnable());

            }


           public void onAnimationRepeat(AnimationparamAnimation){    }

            public void onAnimationStart(AnimationparamAnimation)

            { }

          }

runnable 线程:

 private final classrunnable

              implements Runnable

            {

              private runnable()

              { }


              public void run()

              {

                viewf.setVisibility(View.GONE);//1

                viewg.setVisibility(View.GONE);//2

                viewh.setVisibility(View.GONE);//3

                viewi.setVisibility(View.GONE);//4

                viewj.setVisibility(View.GONE);//5

                viewe.setVisibility(View.GONE);

                intd++;

                if(intd % 5 == 0)//intd

                       setData(viewf);//第一张

                while (true)

                {

                  if (1 == intd % 5)

                    {

                       setData(viewg);

//                     continue;

                    }

                    if (2 == intd % 5)

                    {

                       setData(viewh);

//                     continue;

                    }

                    if (3 == intd % 5)

                    {

                       setData(viewi);

//                     continue;

                    }

                    if (4 == intd % 5)

                       setData(viewj);

                  viewe.setVisibility(View.VISIBLE);

                  viewe.requestFocus();

                  AnimationLoad animation = newAnimationLoad(-90.0F, 0.0F, floata, floatb, floatc, false);

                  animation.setDuration(intk);

                  animation.setFillAfter(true);

                  animation.setInterpolator(newDecelerateInterpolator());//减速

                  animation.setAnimationListener(newAnimation.AnimationListener()

                  {

                    public void onAnimationEnd(AnimationparamAnimation)

                    {

                      AnimationView.this.initView();

                    }


                    public void onAnimationRepeat(AnimationparamAnimation)

                    {

                    }


                    public void onAnimationStart(AnimationparamAnimation)

                    {

                    }

                  });


                  viewe.startAnimation(animation);

                  return;

                }

              }

            }

上述代码中 AnimationLoad 类如下:继承了Animation,使用Camera 以及Matrix  定义了旋转的方式。

  private final floatfloata;

          private final float floatb;

          private final float floatc;

          private final float floatd;

          private final float floate;

          private final boolean boolf;

          private Camera camerag;


          public AnimationLoad(float paramFloat1, floatparamFloat2, float paramFloat3, float paramFloat4, float paramFloat5, booleanparamBoolean)

          {

            this.floata = paramFloat1;//0

            this.floatb = paramFloat2;//90.0f

            this.floatc = paramFloat3;//172

            this.floatd = paramFloat4;//172

            this.floate = paramFloat5;//0

            this.boolf = paramBoolean;

          }


          protected void applyTransformation(floatparamFloat, Transformation paramTransformation)

          {

            float f1 = this.floata;//0.0f

            float f2 = f1 + paramFloat * (this.floatb -f1);//90

            float f3 = this.floatc;//172

            float f4 = this.floatd;//172

            Camera localCamera = this.camerag;

            Matrix localMatrix =paramTransformation.getMatrix();

            localCamera.save();//Saves the camerastate. Each save should be balanced with a call to restore().

           //如果时加速

            if (this.boolf)

              localCamera.translate(0.0F, 0.0F,paramFloat * this.floate);//Applies a translation transform on all three axis

              localCamera.translate(0.0F, 0.0F, this.floate* (1.0F - paramFloat));

            while (true)

            {

              localCamera.rotateY(f2);//Applies arotation transform around the Y axis.

              localCamera.getMatrix(localMatrix);//Computesthe matrix corresponding to the current transformation and copies it to thesupplied matrix object.

              localCamera.restore();//Restores thesaved state, if any

//          localMatrix.postScale(0.5f, 0.5f);//使原来的图像缩放成原来的1/2

              localMatrix.preTranslate(-f3, -f4);

              localMatrix.postTranslate(f3, f4);

              return;

            }

          }

          /**

           * Initialize this animation with thedimensions of the object being animated

           */

          public void initialize(int paramInt1, intparamInt2, int paramInt3, int paramInt4)

          {

            super.initialize(paramInt1, paramInt2,paramInt3, paramInt4);

            this.camerag = new Camera();

          }


分享到此结束,demo 请前往github,  记得给个star哦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354