近期项目需求,在桌面做一个时钟,先上效果图
实现原理,自己做一个时钟背景,时针,分针,秒针,通过获取系统时间来控制时分秒针的角度,实现代码如下
package com.cultraview.mlauncher.view;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.RemoteViews.RemoteView;
import java.util.TimeZone;
import com.cultraview.mlauncher.R;
@RemoteView
public class MKAnalogClock extends View {
private String TAG;
private boolean mAttached;
private Time mCalendar;
private boolean mChanged;
private Drawable mDial;
private int mDialHeight;
private int mDialWidth;
private Drawable mDot;
private final Handler mHandler;
private float mHour;
private Drawable mHourHand;
private final BroadcastReceiver mIntentReceiver;
private Drawable mMinuteHand;
private float mMinutes;
private int mSecond;
private Drawable mSecondHand;
private Handler mSecondHandler;
private SecondThread mTimeThread;
private static final class SecondThread extends Thread {
private boolean isRunning = true;
private Handler myHandler;
private int mySecond;
SecondThread(int second, Handler handler) {
setSecond(second);
this.myHandler = handler;
}
void setRunning(boolean running) {
this.isRunning = running;
}
void setSecond(int second) {
this.mySecond = second;
}
public void run() {
while (this.isRunning) {
this.myHandler.sendEmptyMessage(this.mySecond);
if (this.mySecond == 59) {
this.mySecond = 0;
} else {
this.mySecond++;
}
try {
Thread.sleep(1000);
} catch (Exception e) {
Log.d("MKAnalogClock", "error=" + e.getMessage());
}
}
}
}
public MKAnalogClock(Context context) {
this(context, null);
}
public MKAnalogClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MKAnalogClock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mHandler = new Handler();
this.TAG = getClass().getSimpleName();
this.mSecondHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
MKAnalogClock.this.mSecond = msg.what;
MKAnalogClock.this.postInvalidate();
}
};
this.mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.TIMEZONE_CHANGED")) {
MKAnalogClock.this.mCalendar = new Time(TimeZone.getTimeZone(
intent.getStringExtra("time-zone")).getID());
}
MKAnalogClock.this.onTimeChanged();
}
};
Resources r = this.mContext.getResources();
if (this.mDot == null) {
this.mDot = r.getDrawable(R.drawable.clock_hand_dot);
}
if (this.mDial == null) {
this.mDial = r.getDrawable(R.drawable.clock_dial);
}
if (this.mHourHand == null) {
this.mHourHand = r.getDrawable(R.drawable.clock_hand_hour);
}
if (this.mMinuteHand == null) {
this.mMinuteHand = r.getDrawable(R.drawable.clock_hand_minute);
}
if (this.mSecondHand == null) {
this.mSecondHand = r.getDrawable(R.drawable.clock_hand_second);
}
this.mCalendar = new Time();
this.mDialWidth = this.mDial.getIntrinsicWidth();
this.mDialHeight = this.mDial.getIntrinsicHeight();
}
protected void onAttachedToWindow() { //监听时间广播
super.onAttachedToWindow();
if (!this.mAttached) {
this.mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.TIME_TICK");
filter.addAction("android.intent.action.TIME_SET");
filter.addAction("android.intent.action.TIMEZONE_CHANGED");
getContext().registerReceiver(this.mIntentReceiver, filter, null, this.mHandler);
}
this.mCalendar = new Time();
onTimeChanged();
}
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (this.mAttached) {
getContext().unregisterReceiver(this.mIntentReceiver);
this.mAttached = false;
}
if (this.mTimeThread != null) {
this.mTimeThread.setRunning(false);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != 0 && widthSize < this.mDialWidth) {
hScale = ((float) widthSize) / ((float) this.mDialWidth);
}
if (heightMode != 0 && heightSize < this.mDialHeight) {
vScale = ((float) heightSize) / ((float) this.mDialHeight);
}
float scale = Math.min(hScale, vScale);
setMeasuredDimension(this.mDialWidth, this.mDialHeight);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.mChanged = true;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = this.mChanged;
if (changed) {
this.mChanged = false;
}
int availableWidth = this.mRight - this.mLeft;
int availableHeight = this.mBottom - this.mTop;
int x = availableWidth / 2;
int y = availableHeight / 2;
Drawable dial = this.mDial;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
if (availableWidth < w || availableHeight < h) {
scaled = true;
float scale = Math.min(((float) availableWidth) / ((float) w),
((float) availableHeight) / ((float) h));
canvas.save();
canvas.scale(scale, scale, (float) x, (float) y);
}
if (changed) {
dial.setBounds(x - (w / 2), y - (h / 2), (w / 2) + x, (h / 2) + y);
}
dial.draw(canvas);
canvas.save();
canvas.rotate((this.mHour / 12.0f) * 360.0f, (float) x, (float) y);
Drawable hourHand = this.mHourHand;
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
Paint paintHour = new Paint();
paintHour.setStrokeWidth(6.0f);
paintHour.setAntiAlias(true);
Canvas canvas2 = canvas;
canvas2.drawLine((float) x, (float) y, (float) x, (float) ((y - h) + 15), paintHour);
canvas.restore();
canvas.save();
canvas.rotate((this.mMinutes / 60.0f) * 360.0f, (float) x, (float) y);
Drawable minuteHand = this.mMinuteHand;
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
Paint paintMinute = new Paint();
paintMinute.setStrokeWidth(4.0f);
paintMinute.setAntiAlias(true);
canvas.drawLine((float) x, (float) y, (float) x, (float) ((y - h) + 16), paintMinute);
canvas.restore();
canvas.rotate((((float) this.mSecond) / 60.0f) * 360.0f, (float) x, (float) y);
Drawable secondHand = this.mSecondHand;
w = secondHand.getIntrinsicWidth();
h = secondHand.getIntrinsicHeight();
Paint paintSecond = new Paint();
paintSecond.setStrokeWidth(2.0f);
paintSecond.setAntiAlias(true);
canvas.drawLine((float) x, (float) (y + 20), (float) x, (float) ((y - h) + 23), paintSecond);
Drawable dot = this.mDot;
w = dot.getIntrinsicWidth();
h = dot.getIntrinsicHeight();
if (changed) {
dot.setBounds(x - (w / 2), y - (h / 2), (w / 2) + x, (h / 2) + y);
}
dot.draw(canvas);
if (scaled) {
Log.d(this.TAG, "scale ture");
canvas.restore();
}
}
private void onTimeChanged() {
this.mCalendar.setToNow();
int hour = this.mCalendar.hour;
int minute = this.mCalendar.minute;
this.mSecond = this.mCalendar.second;
this.mMinutes = ((float) minute) + (((float) this.mSecond) / 60.0f);
this.mHour = ((float) hour) + (this.mMinutes / 60.0f);
this.mChanged = true;
if (this.mTimeThread != null) {
this.mTimeThread.setSecond(this.mSecond);
} else {
this.mTimeThread = new SecondThread(this.mSecond, this.mSecondHandler);
this.mTimeThread.start();
}
updateContentDescription(this.mCalendar);
}
private void updateContentDescription(Time time) {
setContentDescription(DateUtils.formatDateTime(this.mContext, time.toMillis(false), 129));
}
}