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哦

你可能感兴趣的:(Android 自定义动画 LoadingView)