Android Canvasに時計を描画する
public static String timeZoneId = "Asia/Tokyo"; //タイムゾーンを変更できるようにする
private void draw() {
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.GRAY);
Paint paint = new Paint();
// 中心座標からCANVAS_SIZE_MINの85%に黒色の円を描画
paint.setColor(Color.BLACK);
canvas.drawCircle(CENTER_POS[0], CENTER_POS[1],
(float) CANVAS_SIZE_MIN / 2f * 0.85f, paint);
// 中心座標からCANVAS_SIZE_MINの80%に白色の円を描画
paint.setColor(Color.WHITE);
canvas.drawCircle(CENTER_POS[0], CENTER_POS[1],
(float) CANVAS_SIZE_MIN / 2f * 0.8f, paint);
// 中心座標からCANVAS_SIZE_MINの70%に文字盤を描画
paint.setColor(Color.BLACK);
paint.setTextSize(CANVAS_SIZE_MIN / 15); // 文字サイズ
float fontPos = CANVAS_SIZE_MIN / 2f * 0.7f; // フォント描画位置
float dialWidth; // 文字の横幅
float dialHeight = paint.descent() + paint.ascent(); // 文字の縦幅
for (int _i = 0; _i < 12; _i++) {
dialWidth = paint.measureText(String.valueOf(_i == 0 ? 12 : _i)); //文字の横幅
canvas.drawText(String.valueOf(_i == 0 ? 12 : _i),
(float) ((Math.sin(Math.toRadians(_i * 30)) * fontPos)
+ CENTER_POS[0]) - (dialWidth / 2),
(float) ((-Math.cos(Math.toRadians(_i * 30)) * fontPos)
+ CENTER_POS[1]) - (dialHeight / 2),
paint);
}
// 針の長さを設定
float HOUR_HAND_LENGTH = (float) CANVAS_SIZE_MIN / 2f * 0.5f; // 短針
float MINUTE_HAND_LENGTH = (float) CANVAS_SIZE_MIN / 2f * 0.6f; // 長針
float SECOND_HAND_LENGTH = (float) CANVAS_SIZE_MIN / 2f * 0.7f; // 秒針
float END_HAND_LENGTH = (float) CANVAS_SIZE_MIN / 2f * 0.1f; //針の尻尾部分
//針の太さを設定
float HOUR_HAND_WIDTH = (float) CANVAS_SIZE_MIN / 30f;
float MINUTE_HAND_WIDTH = (float) CANVAS_SIZE_MIN / 40f;
float SECOND_HAND_WIDTH = (float) CANVAS_SIZE_MIN / 50f;
Date now = new Date(System.currentTimeMillis()); //現在時刻の取得
// 時を取得
DateFormat formatter = new SimpleDateFormat("HH"); // 形式を時間に設定
formatter.setTimeZone(TimeZone.getTimeZone(timeZoneId)); // 選択したタイムゾーンを適用
float hour = Float.parseFloat(formatter.format(now)); // 現在時刻に設定
// 分を取得
formatter = new SimpleDateFormat("mm"); // 形式を分に設定
formatter.setTimeZone(TimeZone.getTimeZone(timeZoneId)); // 設定したタイムゾーンを適用
float minute = Float.parseFloat(formatter.format(now)); // 現在時刻に設定
// 秒を取得
formatter = new SimpleDateFormat("ss"); // 形式を秒に設定
formatter.setTimeZone(TimeZone.getTimeZone(timeZoneId)); // 設定したタイムゾーンを適用
float second = Float.parseFloat(formatter.format(now)); // 現在時刻に設定
// アナログ時計用に短針と長針を修正
// アナログ時計では短針・長針がスムーズに動くため、その修正を加える
// 60秒を100%として、1%=0.6秒、秒 / 0.6で現在の秒針が何%かが分かる
// 1分を100%とし、1%=0.01分、秒針の% * 0.01で+何分したら良いのかが分かる
// 時間も同様に1時間を100%とし、1%=0.01時間、長針の% * 0.01で+何時間したら良いのかが分かる
hour += (minute / 0.6f) * 0.01f;
minute += (second / 0.6f) * 0.01f;
// 針の位置を計算
// 短針の角度 = 時間 * 30, 長針の角度 = 分 * 6, 秒針の角度 = 秒 * 6
// θ = 角度 * π / 180
// x = Sinθ * 針の長さ, y = -Cosθ * 針の長さ で原点からの座標が分かる
float[] hourPos = {(float) Math.sin(Math.toRadians(hour * 30)),
(float) -Math.cos(Math.toRadians(hour * 30))};
float[] minutePos = {(float) Math.sin(Math.toRadians(minute * 6)),
(float) -Math.cos(Math.toRadians(minute * 6))};
float[] secondPos = {(float) Math.sin(Math.toRadians(second * 6)),
(float) -Math.cos(Math.toRadians(second * 6))};
// 短針の描画
paint.setStrokeWidth(HOUR_HAND_WIDTH);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
hourPos[0] * HOUR_HAND_LENGTH + CENTER_POS[0],
hourPos[1] * HOUR_HAND_LENGTH + CENTER_POS[1], paint);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
-hourPos[0] * END_HAND_LENGTH + CENTER_POS[0],
-hourPos[1] * END_HAND_LENGTH + CENTER_POS[1], paint);
// 長針の描画
paint.setStrokeWidth(MINUTE_HAND_WIDTH);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
minutePos[0] * MINUTE_HAND_LENGTH + CENTER_POS[0],
minutePos[1] * MINUTE_HAND_LENGTH + CENTER_POS[1], paint);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
-minutePos[0] * END_HAND_LENGTH + CENTER_POS[0],
-minutePos[1] * END_HAND_LENGTH + CENTER_POS[1], paint);
// 秒針の描画
paint.setStrokeWidth(SECOND_HAND_WIDTH);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
secondPos[0] * SECOND_HAND_LENGTH + CENTER_POS[0],
secondPos[1] * SECOND_HAND_LENGTH + CENTER_POS[1], paint);
canvas.drawLine(CENTER_POS[0], CENTER_POS[1],
-secondPos[0] * END_HAND_LENGTH + CENTER_POS[0],
-secondPos[1] * END_HAND_LENGTH + CENTER_POS[1], paint);
holder.unlockCanvasAndPost(canvas);
}
// 時計更新用のサブクラス
class ClockUpdate extends Thread {
public void run() {
try {
draw();
Thread.sleep(100); // 100/1000秒ごとに更新
} catch (Exception e) {
break;
}
}
}
// 時計更新用のサブクラスをスレッド化
private ClockUpdate clockUpdate = new ClockUpdate();
sinやcos関数が難しい
返信削除