一个模仿小米手机秒表样式的安卓小应用程序,利用自定义控件实现。
开发工具为:Android Studio
大表盘自定义控件:【xiaomiClock 】
public class xiaomiClock extends View {
private Paint textPaint,paint;
private Path mTriangle;
private Timer mTimer;
private float agree = 1;
private Shader mshader;
private PathEffect mEffect;
public xiaomiClock(Context context) {
super(context);
}
public xiaomiClock(Context context, AttributeSet attrs) {
super(context, attrs);
//mEffect = new DashPathEffect(new float[]{1,2,5,10,50,20}, 0); // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}
mEffect = new DashPathEffect(new float[]{5,0}, 0); // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}
mshader = new SweepGradient(500, 500, Color.parseColor("#3b3b3b"), Color.parseColor("#ffffff")); //渐变遮罩样式
textPaint = new Paint();
textPaint.setStrokeWidth(16);
textPaint.setColor(Color.WHITE);
textPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint.setAntiAlias(true);
paint = new Paint();
paint.setAntiAlias(true);
mTriangle = new Path();
mTriangle.moveTo(960, 500);// 此点为多边形的顶点【三角形(指针)】
//下面两个x 相等,表示底边的位置
mTriangle.lineTo(1000, 525); // y:底边宽的其中一个顶点
mTriangle.lineTo(1000, 475); //y:底边宽的其中一个顶点
mTriangle.close();
setmTimer();
System.out.println("度数" + ((float) 6.0 / 10));
}
@Override
protected void onDraw(Canvas canvas) {
//绘画手表盘
drawbeauty(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//设置宽高
setMeasuredDimension(1000,1000); //画布大小
}
public void drawbeauty(Canvas canvas) {
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//设置缓存层,因为下面要实用xfermode,使用xfemode必须使用缓存层,否则会出现黑色背景
int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);
//初始化画笔,因为上下两层做画需要的画笔属性不一样,所以只能每次重新设置一次
paint.setStyle(Paint.Style.STROKE); //设置画笔为不填充模式
paint.setPathEffect(mEffect); //设置笔画样式,这里设置的是虚线样式
paint.setStrokeWidth(50); //设置笔画宽度
canvas.drawCircle(500, 500, 420, paint); //画一个纯色表盘,虚线,空心圆形 【表盘位置和大小】
//设置画笔属性,SRC_IN属性,让第二个图案只能花在第一个图案上面,也就是只能画在上面所说那个纯色表盘里面
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//把画笔虚线属性去掉,因为我要的是一个实心圆形,然后让这个实心但是颜色不一样圆形画在上面所说表盘上面,因为设置了xfermode,所以显示的一样会是虚线圆形表盘,但是颜色会变成你现在的颜色
paint.setPathEffect(null);
//设置画笔shader属性,这里设置的是SweepGradient模式,可以让颜色过渡泾渭分明,以圆形为中心开始变化
paint.setShader(mshader);
paint.setStyle(Paint.Style.FILL);
canvas.save(); //保存画布
//旋转画布,然后你就会发现时钟表盘开始动了
canvas.rotate(agree, 500, 500); //画布旋转的中心点
canvas.drawRect(10, 10, 1000, 1100, paint); //渐变矩形绘制
canvas.drawPath(mTriangle, textPaint); //绘制小三角形
canvas.restore();
//最后将画笔去除Xfermode
paint.setXfermode(null);
canvas.restoreToCount(layerId);
}
private void setmTimer() {
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
agree = agree + 0.022f;//数值越大,旋转速度越快
if (agree > 360)
agree = 1;
postInvalidate();
}
}, 1000, 3); //延时/周期
}
}
小码表表盘自定义控件:【xiaomiClock 02】
public class xiaomiClock02 extends View {
private Paint textPaint,paint;
private Path mTriangle;
private Timer mTimer;
private float agree = 1;
private Shader mshader;
private PathEffect mEffect;
public xiaomiClock02(Context context) {
super(context);
}
public xiaomiClock02(Context context, AttributeSet attrs) {
super(context, attrs);
//mEffect = new DashPathEffect(new float[]{1,2,5,10,50,20}, 0); // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}
mEffect = new DashPathEffect(new float[]{5,0}, 0); // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}
mshader = new SweepGradient(110, 110, Color.parseColor("#3b3b3b"), Color.parseColor("#ffffff")); //渐变遮罩样式【渐变色的渐变中心点以及颜色】
textPaint = new Paint();
textPaint.setStrokeWidth(16);
textPaint.setColor(Color.WHITE);
textPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint.setAntiAlias(true);
paint = new Paint();
paint.setAntiAlias(true);
mTriangle = new Path();
mTriangle.moveTo(190, 110);// 此点为多边形的顶点【三角形(指针)】
//下面两个x 相等,表示底边的位置
mTriangle.lineTo(110, 112); // y:底边宽的其中一个顶点
mTriangle.lineTo(110, 108); //y:底边宽的其中一个顶点
mTriangle.close();
setmTimer();
System.out.println("度数" + ((float) 6.0 / 10));
}
@Override
protected void onDraw(Canvas canvas) {
//绘画手表盘
drawbeauty(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//设置宽高
setMeasuredDimension(220,220); //画布大小
}
public void drawbeauty(Canvas canvas) {
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//设置缓存层,因为下面要实用xfermode,使用xfemode必须使用缓存层,否则会出现黑色背景
int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);
//初始化画笔,因为上下两层做画需要的画笔属性不一样,所以只能每次重新设置一次
paint.setStyle(Paint.Style.STROKE); //设置画笔为不填充模式
paint.setPathEffect(mEffect); //设置笔画样式,这里设置的是虚线样式
paint.setStrokeWidth(2); //设置笔画宽度
canvas.drawCircle(110, 110, 100, paint); //画一个纯色表盘,虚线,空心圆形 【表盘位置和大小】
//设置画笔属性,SRC_IN属性,让第二个图案只能花在第一个图案上面,也就是只能画在上面所说那个纯色表盘里面
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//把画笔虚线属性去掉,因为我要的是一个实心圆形,然后让这个实心但是颜色不一样圆形画在上面所说表盘上面,因为设置了xfermode,所以显示的一样会是虚线圆形表盘,但是颜色会变成你现在的颜色
paint.setPathEffect(null);
//设置画笔shader属性,这里设置的是SweepGradient模式,可以让颜色过渡泾渭分明,以圆形为中心开始变化
paint.setShader(mshader);
paint.setStyle(Paint.Style.FILL);
canvas.save(); //保存画布
//旋转画布,然后你就会发现时钟表盘开始动了
canvas.rotate(agree, 110, 110); //画布旋转的中心点
canvas.drawRect(1, 1, 220, 220, paint); //渐变矩形绘制
canvas.drawPath(mTriangle, textPaint); //绘制小三角形
canvas.restore();
//最后将画笔去除Xfermode
paint.setXfermode(null);
canvas.restoreToCount(layerId);
}
private void setmTimer() {
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
agree = agree + 0.2f + 1f;//数值越大,旋转速度越快
if (agree > 360)
agree = 1;
postInvalidate();
}
}, 1000, 3); //延时/周期
}
}
BaseActivity设置主题为黑色
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//主题设置
setTheme(R.style.AppTheme01);
}
}
主题Styles样式
MainActivity 设置时间代码
public class MainActivity extends BaseActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DataThread().start(); //时间控制线程
}
//设定显示系统时间
private String getData() {
long sysTime = System.currentTimeMillis();
CharSequence sysTimeStr = DateFormat.format("" + "yyyy/MM/dd", sysTime);
return (String) sysTimeStr;
}
@SuppressLint("HandlerLeak")
private Handler mHandlerData = new Handler() {
public void handleMessage(android.os.Message msg) {
TextView textView = findViewById(R.id.Time_TextView01); //确定系统时间变化的控件
textView.setText((String) msg.obj);
}
};
//设定显示系统时间
private String getTime() {
long sysTime = System.currentTimeMillis();
CharSequence sysTimeStr = DateFormat.format("" + "HH:mm:ss", sysTime);
return (String) sysTimeStr;
}
@SuppressLint("HandlerLeak")
private Handler mHandlerTime = new Handler() {
public void handleMessage(android.os.Message msg) {
TextView textView = findViewById(R.id.Time_TextView02); //确定系统时间变化的控件
textView.setText((String) msg.obj);
}
};
private class DataThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 999999999; i++) { //一共变化多少次次
try {
Thread.sleep(10); //每一毫秒变化一次
} catch (InterruptedException e) {
e.printStackTrace();
}
final String sysTime = getTime();
final String sysData = getData();
// 只能在主线程中修改ui控件
mHandlerData.sendMessage(mHandlerData.obtainMessage(0, sysData)); //系统日期
mHandlerTime.sendMessage(mHandlerTime.obtainMessage(0, sysTime)); //系统时间
}
}
}
}
.
App下载:https://aifabu.com/iUfi
源码下载:https://download.csdn.net/download/erp_lxkun_jak/11240191
【注意:使用开发工具是 Android Studio 哦!】
.
.
感谢你的查阅,希望可以帮到你,祝你学习愉快!