您的位置:首页 > 移动开发 > Android开发

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

2017-06-06 11:03 316 查看

项目需要写了一个简单的加载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();
}
});
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  控件