AnalogClockを作ってみる。

この間の続きで、今度はアナログ時計を作ってみた。

AnalogClockView.javaを作る

package com.example.analogclock;
 
import java.util.Calendar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
 
public class AnalogClockView extends View {
	private int centerX = 0;
	private int centerY = 0;
	private int handLength = 0;
 
	private HandPoint sec;
	private HandPoint min;
	private HandPoint hour;
 	
	public AnalogClockView(Context context) {
		super(context);
		sec = new HandPoint(centerX, centerY);
		min = new HandPoint(centerX, centerY);
		hour = new HandPoint(centerX, centerY);
	}
 
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
 		
		getTodayNow();
 		
		Paint paint = new Paint();
		paint.setAntiAlias(true);
 	
		paint.setColor(Color.WHITE);
		canvas.drawLine(centerX, centerY, sec.X(), sec.Y(), paint);
		paint.setColor(Color.BLUE);
		canvas.drawLine(centerX, centerY, min.X(), min.Y(), paint);
		paint.setColor(Color.RED);
		canvas.drawLine(centerX, centerY, hour.X(), hour.Y(), paint);
	}
 
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		centerX = w / 2;
		centerY = h / 2;
		handLength = Math.min(centerX, centerY);
	}
 
	private void getTodayNow(){
		Calendar cal = Calendar.getInstance();
		double ss = (double)cal.getTime().getSeconds();
		double mm = (double)cal.getTime().getMinutes();
		double hh = (double)cal.getTime().getHours();
 		
		double secAng = 2.0 * Math.PI * ss / 60.0;
		double minAng = 2.0 * Math.PI * (mm + ss/60.0)/60.0;
		double hourAng = 2.0 * Math.PI * (hh+mm/60.0)/12.0;
 		
		sec.setPoint((int)(centerX+Math.sin(secAng)*handLength*0.7), (int)(centerY-Math.cos(secAng)*handLength*0.7));
		min.setPoint((int)(centerX+Math.sin(minAng)*handLength*0.9), (int)(centerY-Math.cos(minAng)*handLength*0.9));
		hour.setPoint((int)(centerX+Math.sin(hourAng)*handLength*0.5), (int)(centerY-Math.cos(hourAng)*handLength*0.5));
	}
}

座標位置を保存するだけのクラスも作った(C#でいうプロパティみたいなので書けないのか?Javaは)。

package com.example.analogclock;
public class HandPoint {
	private int posx;
	private int posy; 
	public int X() {
		return posx;
	}
	public int Y() {
		return posy;
	}
	public void setPoint(int _x, int _y) {
		posx = _x;
		posy = _y;
	}
	public HandPoint(int _x, int _y) {
		posx = _x;
		posy = _y;
	}
}

で、これをAnalogClockのActivityから、定期実行で呼ぶ。

package com.example.analogclock;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
 
public class AnalogClock extends Activity {
	private Handler handler = new Handler();
	private Runnable runnable;
	private static long CLOCK_INTERVAL=1000;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final AnalogClockView view = new AnalogClockView(getApplication());
        setContentView(view);
        runnable = new Runnable(){
        @Override
        public void run(){
        	view.invalidate();
        	handler.postDelayed(this, CLOCK_INTERVAL);
        }
        };
    	handler.postDelayed(runnable, CLOCK_INTERVAL);
    }
}

view.invalidate();が味噌だな。view.onDraw();とかしちゃいけない。

ダサいけど、とりあえず動く。

時計を動かしたいだけなら

実は、SDKコンポーネントの中に時計のコンポーネントもあるので、ただ時計を画面上で動かしたいだけなら、実はこんなことをしなくても良い。
ただ、res/layout/main.xmlを記述するだけ。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<AnalogClock android:id="@+id/AnalogClock01" 
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content" />
	<DigitalClock android:text="@+id/DigitalClock01"
		android:id="@+id/DigitalClock01"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content" 
		android:textSize="48sp"/>
</LinearLayout>


こっちのほうが、そもそも簡単でカッコいい。