android 自定义控件---简单的加载View

项目需要写了一个简单的加载View,看效果:

这里写图片描述

秒针在右半圆(-90度到90度)慢速旋转,左半圆(90度到270度)快速旋转。

由于注释写的已经很详细了,直接上代码:

Loading:

/**
 * loading 工具类
 *
 * @author zyc
 *         created at 2017/6/5 11:39
 */
public class Loading extends View {

  // 圆环画笔
  private Paint mCirclePaint;
  // 时针画笔
  private Paint mTimePaint;
  // 半径 50px
  private int radius = 50;
  // 秒针长度
  private int secondLength = 60;
  // 不动针长度
  private int minuteLength = 30;
  // 旋转状态--默认true
  private boolean rotate = true;
  // 变化角度--初始12点钟方向
  private int changeAn = -90;
  // 属性动画
  private ValueAnimator valueAnimator;
  // 圆心坐标x
  private int xCenter = 100;
  // 圆心坐标y
  private int yCenter = 100;
  // 旋转终点x坐标
  private int xStop = xCenter;
  // 旋转终点y坐标
  private int yStop = secondLength;
  public Context context;

  public Loading(Context context) {
    this(context, null);
  }

  public Loading(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    this.context = context;

    initView();
  }

  /**
   * 初始化工具
   */
  private void initView() {
    //初始化半径
    radius = dip2px(16);
    // 初始化秒针长度
    secondLength = dip2px(14);
    // 初始化分针长度
    minuteLength = dip2px(10);

    // 画圆画笔
    if (mCirclePaint == null) {
      mCirclePaint = new Paint();
    }
    mCirclePaint.setDither(true);
    mCirclePaint.setAntiAlias(true);
    mCirclePaint.setColor(getResources().getColor(android.R.color.white));
    mCirclePaint.setStyle(Paint.Style.STROKE);
    //stroke 宽度
    mCirclePaint.setStrokeWidth(3);
    // 时针画笔--画线
    if (mTimePaint == null) {
      mTimePaint = new Paint();
    }
    mTimePaint.setDither(true);
    mTimePaint.setAntiAlias(true);
    mTimePaint.setColor(getResources().getColor(android.R.color.white));
    mTimePaint.setStyle(Paint.Style.FILL);
    //stroke 宽度
    mTimePaint.setStrokeWidth(5);

    if (rotate){
      startRotate();
    }
  }

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
    if (widthSpecMode == MeasureSpec.AT_MOST
        && heightSpecMode == MeasureSpec.AT_MOST) {
      setMeasuredDimension(100, 100);
    } else if (widthSpecMode == MeasureSpec.AT_MOST) {
      setMeasuredDimension(100, heightSpecSize);
    } else if (heightSpecMode == MeasureSpec.AT_MOST) {
      setMeasuredDimension(widthSpecSize, 100);
    }
  }

  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 取中心位置
    yCenter = xCenter = getWidth() / 2;
    // 画圆
    canvas.drawCircle(xCenter, yCenter, radius, mCirclePaint);
    // 画秒针--动
    if (rotate) {
      canvas.drawLine(xCenter, yCenter, xStop, yStop, mTimePaint);
    } else {
      canvas.drawLine(xCenter, yCenter, xCenter, secondLength, mTimePaint);
    }
    // 画时针--不动
    canvas.drawLine(xCenter, yCenter, xCenter + minuteLength, yCenter, mTimePaint);
  }

  /**
   * 旋转秒针
   */
  private void rorateSecond() {
    valueAnimator = new ValueAnimator().ofInt(0, 60000);
    valueAnimator.setRepeatMode(ValueAnimator.RESTART);
    valueAnimator.setDuration(60000);
    valueAnimator.start();
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override public void onAnimationUpdate(ValueAnimator animation) {
        //计算终点坐标
        // 弧度
        float angle = (float) ((Math.PI / 180) * (changeAn));
        xStop = (int) (xCenter + (radius - 10) * Math.cos(angle));
        yStop = (int) (yCenter + (radius - 10) * Math.sin(angle));
        changeAn++;
        // 270 一圈 置为-90
        if (changeAn >= 270) {
          changeAn = -90;
        }
        //changeAn > 90 && changeAn < 270 快速旋转 否则慢速旋转
        if (changeAn >= 90 && changeAn < 270) {
          changeAn = changeAn + 5;
        }
        // 重绘
        postInvalidate();
      }
    });
  }

  /**
   * 开始旋转动画
   */
  public void startRotate() {
    changeAn = -90;
    rotate = true;
    rorateSecond();
  }

  /**
   * 停止旋转动画
   */
  public void stopRotate() {
    rotate = false;
    if (valueAnimator != null && valueAnimator.isRunning()) {
      valueAnimator.cancel();
    }
    changeAn = -90;
  }

  /**
   * convert dp to px
   */
  public int dip2px(float dpValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
  }
}

LoadingActivity:

/**
 * 测试 加载 view
*@author zyc
*created at 2017/6/5 12:07
*/

public class LoadingActivity extends Activity{

  @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_loading);

    initView();
  }

  private void initView() {
    final Loading load = (Loading) findViewById(R.id.loading);
    findViewById(R.id.tv_start).setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        DialogLoading.showDialog(LoadingActivity.this);
      }
    });
    findViewById(R.id.tv_stop).setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        DialogLoading.closeDialog();
      }
    });
  }
}

activity_loading.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    >

  <com.lefu8.www.loadingdemo.views.Loading
      android:id="@+id/loading"
      android:layout_width="100dp"
      android:layout_height="100dp"
      android:layout_gravity="center_horizontal"
      >
  </com.lefu8.www.loadingdemo.views.Loading>

  <TextView
      android:id="@+id/tv_start"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="开启动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
  <TextView
      android:id="@+id/tv_stop"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="关闭动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
  <TextView
      android:id="@+id/tv_stop1"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="关闭动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
  <TextView
      android:id="@+id/tv_stop2"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="关闭动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
  <TextView
      android:id="@+id/tv_stop3"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="关闭动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
  <TextView
      android:id="@+id/tv_stop4"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:gravity="center"
      android:text="关闭动画"
      android:textColor="@android:color/holo_red_light"
      android:textSize="30sp"
      />
</LinearLayout>

DialogLoading:

/**
 * 封装的dialog
*@author zyc
*created at 2017/6/6 11:01
*/

public class DialogLoading {
  /**
   * 通用显示等待对话框
   */
  public static void showDialog(final Activity act) {
    act.runOnUiThread(new Runnable() {
      @Override public void run() {
        waitingDialog = getWaitingDialog(act);
        waitingDialog.show();
      }
    });
  }

  private static volatile Dialog waitingDialog;

  private static Dialog getWaitingDialog(Activity act) {
    if (waitingDialog != null) {
      waitingDialog = null;
    }
    waitingDialog = new Dialog(act,R.style.my_dialog  );
    waitingDialog.setContentView(R.layout.layout_loading);
    waitingDialog.setCancelable(true);
    waitingDialog.setCanceledOnTouchOutside(false);
    Window w = waitingDialog.getWindow();
    w.setGravity(Gravity.CENTER);
    WindowManager.LayoutParams attributes = w.getAttributes();
    attributes.alpha = 0.6f; // 透明度
    w.setAttributes(attributes);
    return waitingDialog;
  }

  /**
   * 通用关闭等待对话框 synchronized避免并发访问 在调用showDialog()的类的onPause中,
   * 加上Tools.closeDialog();是很好的做法,能够避免窗口泄露
   */
  public static synchronized void closeDialog() {
    try {
      if (waitingDialog != null) {
        if (waitingDialog.isShowing()) {
          waitingDialog.cancel();
        }
        waitingDialog = null;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 通用显示等待对话框,不可取消
   */
  public static void showDialogUnCancelable(final Activity act) {
    act.runOnUiThread(new Runnable() {
      @Override public void run() {
        waitingDialog = getWaitingDialog(act);
        waitingDialog.setCancelable(false);
        waitingDialog.show();
      }
    });
  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值