Android自定义加载loading view动画组件

在github上找的一个有点酷炫的loading动画https://github.com/Fichardu/CircleProgress

我写写使用步骤

自定义view(CircleProgress )的代码

package com.hysmarthotel.view;

import com.hysmarthotel.roomcontrol.R;
import com.hysmarthotel.util.EaseInOutCubicInterpolator;

import android.animation.TimeInterpolator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationUtils;

public class CircleProgress extends View {

 private static final int RED = 0xFFE5282C;
 private static final int YELLOW = 0xFF1F909A;
 private static final int BLUE = 0xFFFC9E12;
 private static final int COLOR_NUM = 3;
 private int[] COLORS;
 private TimeInterpolator mInterpolator = new EaseInOutCubicInterpolator();

 private final double DEGREE = Math.PI / 180;
 private Paint mPaint;
 private int mViewSize;
 private int mPointRadius;
 private long mStartTime;
 private long mPlayTime;
 private boolean mStartAnim = false;
 private Point mCenter = new Point();

 private ArcPoint[] mArcPoint;
 private static final int POINT_NUM = 15;
 private static final int DELTA_ANGLE = 360 / POINT_NUM;
 private long mDuration = 3600;

 public CircleProgress(Context context) {
  super(context);
  init(null, 0);
 }

 public CircleProgress(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(attrs, 0);
 }

 public CircleProgress(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init(attrs, defStyle);
 }

 private void init(AttributeSet attrs, int defStyle) {
  mArcPoint = new ArcPoint[POINT_NUM];

  mPaint = new Paint();
  mPaint.setAntiAlias(true);
  mPaint.setStyle(Paint.Style.FILL);

  TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircleProgress, defStyle, 0);
  int color1 = a.getColor(R.styleable.CircleProgress_color1, RED);
  int color2 = a.getColor(R.styleable.CircleProgress_color2, YELLOW);
  int color3 = a.getColor(R.styleable.CircleProgress_color3, BLUE);
  a.recycle();

  COLORS = new int[]{color1, color2, color3};
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int defaultSize = getResources().getDimensionPixelSize(R.dimen.default_circle_view_size);
  int width = getDefaultSize(defaultSize, widthMeasureSpec);
  int height = getDefaultSize(defaultSize, heightMeasureSpec);
  mViewSize = Math.min(width, height);
  setMeasuredDimension(mViewSize, mViewSize);
  mCenter.set(mViewSize / 2, mViewSize / 2);

  calPoints(1.0f);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  canvas.save();
  canvas.translate(mCenter.x, mCenter.y);

  float factor = getFactor();
  canvas.rotate(36 * factor);
  float x, y;
  for (int i = 0; i < POINT_NUM; ++i) {
   mPaint.setColor(mArcPoint[i].color);
   float itemFactor = getItemFactor(i, factor);
   x = mArcPoint[i].x - 2 * mArcPoint[i].x * itemFactor;
   y = mArcPoint[i].y - 2 * mArcPoint[i].y * itemFactor;
   canvas.drawCircle(x, y, mPointRadius, mPaint);
  }

  canvas.restore();

  if (mStartAnim) {
   postInvalidate();
  }
 }

 private void calPoints(float factor) {
  int radius = (int) (mViewSize / 3 * factor);
  mPointRadius = radius / 12;

  for (int i = 0; i < POINT_NUM; ++i) {
   float x = radius * -(float) Math.sin(DEGREE * DELTA_ANGLE * i);
   float y = radius * -(float) Math.cos(DEGREE * DELTA_ANGLE * i);

   ArcPoint point = new ArcPoint(x, y, COLORS[i % COLOR_NUM]);
   mArcPoint[i] = point;
  }
 }

 private float getFactor() {
  if (mStartAnim) {
   mPlayTime = AnimationUtils.currentAnimationTimeMillis() - mStartTime;
  }
  float factor = mPlayTime / (float) mDuration;
  return factor % 1f;
 }

 private float getItemFactor(int index, float factor) {
  float itemFactor = (factor - 0.66f / POINT_NUM * index) * 3;
  if (itemFactor < 0f) {
   itemFactor = 0f;
  } else if (itemFactor > 1f) {
   itemFactor = 1f;
  }
  return mInterpolator.getInterpolation(itemFactor);
 }

 public void startAnim() {
  mPlayTime = mPlayTime % mDuration;
  mStartTime = AnimationUtils.currentAnimationTimeMillis() - mPlayTime;
  mStartAnim = true;
  postInvalidate();
 }

 public void reset() {
  stopAnim();
  mPlayTime = 0;
  postInvalidate();

 }

 public void stopAnim() {
  mStartAnim = false;
 }

 public void setInterpolator(TimeInterpolator interpolator) {
  mInterpolator = interpolator;
 }

 public void setDuration(long duration) {
  mDuration = duration;
 }

 public void setRadius(float factor) {
  stopAnim();
  calPoints(factor);
  startAnim();
 }

 static class ArcPoint {
  float x;
  float y;
  int color;

  ArcPoint(float x, float y, int color) {
   this.x = x;
   this.y = y;
   this.color = color;
  }
 }

}

EaseInOutCubicInterpolator是自定义view(CircleProgress )中要是用的一个工具

package com.hysmarthotel.util;

import android.animation.TimeInterpolator;

public class EaseInOutCubicInterpolator implements TimeInterpolator {

 @Override
 public float getInterpolation(float input) {
  if ((input *= 2) < 1.0f) {
   return 0.5f * input * input * input;
  }
  input -= 2;
  return 0.5f * input * input * input + 1;
 }

}

在activity中的调用(还有一些其他用法可以自己看看github上的源代码)

mProgressView = (CircleProgress)findViewById(R.id.progress_vie);
mProgressView.startAnim(); //开始
mProgressView.stopAnim(); //结束
mProgressView.setRadius(factor); //半径
mProgressView.reset(); //复原

在xml文件中的布局

<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:circleprogress="http://schemas.android.com/apk/res/com.hysmarthotel.roomcontrol"  //这个地方记得要加 //包名
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@drawable/bg1" >

 <com.hysmarthotel.view.CircleProgress                   //类名
  android:id="@+id/progress_vie"
  android:layout_x="350.5px"
  android:layout_y="150.0px"
  android:layout_width="1140.0px"
  android:layout_height="700.0px"
  circleprogress:color1="@android:color/holo_red_light"   //这些参数就是通过xmlns:circleprogress,和attrs文件相关联的     circleprogress:color2="@android:color/holo_green_light"     circleprogress:color3="@android:color/holo_blue_light" />

自己在values目录中新建的attrs文件,这是与自定义view中自定义参数相关的

 <declare-styleable name="CircleProgress">
  <attr name="color1" format="reference|color"/>
  <attr name="color2" format="reference|color"/>
  <attr name="color3" format="reference|color"/>
 </declare-styleable>

自己在values目录中新建的dimens文件,这个只是几个颜色参数

 <?xml version="1.0" encoding="utf-8"?>
<resources>
 <dimen name="activity_horizontal_margin">16dp</dimen>
 <dimen name="activity_vertical_margin">16dp</dimen>
 <dimen name="default_circle_view_size">200dp</dimen>
</resources>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义View实现loading动画加载效果

    项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. 先自定义一个View,继承自LinearLayout,在Layout中,添加布局控件 /** * Created by xiedong on 2017/3/7. */ public class Loading_view extends LinearLayout { private Context m

  • Android中自定义加载样式图片的具体实现

    先让大家看看效果图吧,相信很多Android初学者都想知道这中效果是怎么实现的,来上图: 想实现上面这张图中的自定义加载样式,其实很简单,首先我们需要的布局组件有ProcessBar和TextView,下面是布局文件的代码(只是加载的页面的布局): 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.an

  • Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题

    前言 之前在做一个Viewpager上面加载多个Fragment时总会实例化已经创建好的Fragmnet对象类似 viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { switch(position){ case 0: fragments=new Fragmnet01(); break; case

  • Android自定义下拉刷新上拉加载

    本文实例为大家分享了Android自定义下拉刷新上拉加载的具体实现步骤,供大家参考,具体内容如下 实现的方式是SwipeRefreshLayout + RecyclerView 的VIewType 首先看效果: 总的思路: 布局文件 <android.support.v4.widget.SwipeRefreshLayout android:layout_marginTop="?attr/actionBarSize" android:id="@+id/one_refres

  • 加载页面遮挡耗时操作任务页面--第三方开源之AndroidProgressLayout

    AndroidProgressLayout实现为界面添加圆形进度条.调用setprogress()方法显示和隐藏进度条 在Android的开发中,往往有这种需求,比如一个耗时的操作,联网获取网络图片.内容,数据库耗时读写等等,在此耗时操作过程中,开发者也许不希望用户再进行其他操作(其他操作可能会引起逻辑混乱),而此时需要给用户一个额外的加载页面遮挡住主逻辑代码的运行,待主页面的耗时操作完成后,自动消失这样加载过度页面,恢复出正常应该显示的页面. 举个实际的例子,如代码使用Android WebV

  • Android自定义Dialog实现文字动态加载效果

    之前在技术问答上面看到一个提问 "加载中-" 后面三个点是动态的,这么一个效果实现.想来想去,好像没想到好的处理方式. 尝试了一下,以一个最笨的方式实现了.先来看一下效果 : 我是通过自定义一个Dialog,加载中的效果,是在Dialog内部实现的,进度还是从Activity里面控制的. 下面是Dialog实现类: public class CustomDialog extends AlertDialog { public CustomDialog(Context context) {

  • Android中替换WebView加载网页失败时的页面

    我们用webView去请求一个网页链接的时候,如果请求网页失败或无网络的情况下,它会返回给我们这样一个页面,如下图所示: 上面这个页面就是系统自带的页面,你觉得是不是很丑?反正小编本人觉得非常丑,很难看,于是乎小编就在想能不能自定义一个页面,当数据请求失败时让系统来加载我们自定义好的页面?上网查了很多资料,都没有关于这个问题的解决方法(反正我是没有找到),经过小编的不断琢磨,今天终于实现了这个功能.以下就是本人自定义实现的数据加载失败时的页面: 这样看起来是不是觉得很高大尚.这和我们真正拿到数据

  • Android实现自定义加载框的代码示例

    App在与服务器进行网络交互的时候,需要有一个提示的加载框,如图: 此时我们可以自定义一个加载中的对话框,代码如下: public class LoadingDialog extends Dialog { private static final int CHANGE_TITLE_WHAT = 1; private static final int CHNAGE_TITLE_DELAYMILLIS = 300; private static final int MAX_SUFFIX_NUMBER

  • Android自定义view实现阻尼效果的加载动画

    效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

  • Android自定义加载控件实现数据加载动画

    本文实例为大家分享了Android自定义加载控件,第一次小人跑动的加载效果眼前一亮,相比传统的PrograssBar高大上不止一点,于是走起,自定义了控件LoadingView去实现动态效果,可直接在xml中使用,具体实现如下 package com.*****.*****.widget; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.util.

  • Android开发实现自定义新闻加载页面功能实例

    本文实例讲述了Android开发实现自定义新闻加载页面功能.分享给大家供大家参考,具体如下: 一.概述: 1.效果演示: 2.说明:在新闻页面刚加载的时候,一般会出现五种状态 未知状态(STATE_UNKNOW).空状态(STATE_EMPTY).加载中(STATE_LOADING).错误(STATE_ERROT).成功(STATE_SUCCESS) 因为每个Detail页面都会出现,所以我们可以把他们封装成一个LoadPage的自定义view,可以复用 二.实现: 1.首先的定义三个布局,为什

随机推荐