カスタムView(2)

15756 ワード

一、概説
前編ではカスタムビューの基礎知識を分析しましたが、まだカスタムビューが分からない場合は前編ブログのカスタムビュー(一)をご覧ください.これは主に、独自のViewの簡単な例です.クロック効果です.以下のように動作します.
実はこの効果の前に1篇のホームページ版を書いたことがあって、HTML 5のcontextを利用して書いたので、興味があるのは見てみることができます.
簡単な分析の下で:図からこのカスタムViewが1つの円、3つのポインタの直線、それから断直線であることを見ることができて、その自動走行はpostシリーズの方法でonDrawを繰り返し呼び出すことができます.ここでのポイントはcanvasのrotate,translateの2つの方法の柔軟な使用です.
二、コード
レイアウトは次のとおりです.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <com.lw.myclock.MyClock
        android:layout_width="300dp"
        android:layout_height="300dp"
        />

</RelativeLayout>

ブラシを作成し、ブラシのstyleと色を設定する初期化方法
public void init(){
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
        //    
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(3);
    }

現在時刻の取得
    //      
    d = new Date();
    int hours = d.getHours();
    int minutes = d.getMinutes();

次に本格的に描き始めます.主にcanvasのtranslate()でキャンバスの中心点を設定し、rotat()eを呼び出してキャンバスの回転を制御して短線を描きます.

        //1.  
        canvas.translate(150, 150);
        canvas.drawCircle(0, 0, radius, mPaint);
        //2.      
        for (int i = 0; i <= 11 ; i++) {
            mPaint.setStrokeWidth(3);
            canvas.drawLine(0, -150, 0, -135, mPaint) ;
            mPaint.setStrokeWidth(1);
            if( i == 0 ){
                canvas.drawText(12 + "",-5,-130,mPaint) ;
            }else{
                canvas.drawText(i + "",-5,-130,mPaint) ;
            }
            canvas.rotate(30) ;
        }
        //      
        for (int i = 0; i < 60 ; i++) {
            mPaint.setStrokeWidth(1) ;
            canvas.drawLine(0, -150, 0, -145, mPaint) ;
            canvas.rotate(6);
        }

ここでは,描画を開始するたびにsave()メソッドを呼び出し,描画するたびにrestore()メソッドを呼び出す.

    //       
        canvas.save() ;
        mPaint.setStrokeWidth(4);
        canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  );
        canvas.drawLine(0, 10, 0, -90, mPaint);
        canvas.restore() ;
        //       
        canvas.save() ;
        mPaint.setStrokeWidth(2);
        //       ,       12   
        System.out.println("minutes:" + minutes * 6 );
        canvas.rotate(minutes * 6 ) ;
        canvas.drawLine(0, 10, 0, -100, mPaint);
        canvas.restore() ;
        //      
        canvas.save() ;
        mPaint.setStrokeWidth(1);
        canvas.rotate(seconds * 6 );
        System.out.println("seconds:" + seconds);
        canvas.drawLine(0, 10, 0, -120, mPaint) ;
        canvas.restore() ;
        //     
        canvas.save() ;
        mPaint.setStrokeWidth(3);
        canvas.drawCircle(0, 0, 2, mPaint);
        canvas.restore() ;

ここで複雑なのは時計の角度の変化です
canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  ) ;

この時間が11時30分であれば、11時はhours*30、30分回転の角度は(minutes*6)*30/360です.
次にpostメソッドの各1 s呼び出しを呼び出します.すべてのコードは次のとおりです.
package com.lw.myclock;

import java.util.Date;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
/** *       * @author lw * */
public class MyClock extends View {

    private Paint mPaint = new Paint();
    private Date d;

    public MyClock(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public MyClock(Context context) {
        this(context,null);
    }
    public void init(){
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
        //    
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(3);
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();
        int paddingBottom = getPaddingBottom();
        int paddingTop = getPaddingTop();
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        width = width - paddingLeft - paddingRight ;
        height = height - paddingBottom - paddingTop ;
        //300 300 
        //      
        d = new Date();
        int hours = d.getHours();
        int minutes = d.getMinutes();
        int seconds = d.getSeconds();
        int radius = Math.min(width, height) / 2 ;
        //1.  
        canvas.translate(150, 150);
        canvas.drawCircle(0, 0, radius, mPaint);
        //2.      
        for (int i = 0; i <= 11 ; i++) {
            mPaint.setStrokeWidth(3);
            canvas.drawLine(0, -150, 0, -135, mPaint) ;
            mPaint.setStrokeWidth(1);
            if( i == 0 ){
                canvas.drawText(12 + "",-5,-130,mPaint) ;
            }else{
                canvas.drawText(i + "",-5,-130,mPaint) ;
            }
            canvas.rotate(30) ;
        }
        //      
        for (int i = 0; i < 60 ; i++) {
            mPaint.setStrokeWidth(1) ;
            canvas.drawLine(0, -150, 0, -145, mPaint) ;
            canvas.rotate(6);
        }
        //       
        canvas.save() ;
        mPaint.setStrokeWidth(4);
        canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  ) ;
        canvas.drawLine(0, 10, 0, -90, mPaint);
        canvas.restore() ;
        //       
        canvas.save() ;
        mPaint.setStrokeWidth(2);
        //       ,       12   
        System.out.println("minutes:" + minutes * 6 );
        canvas.rotate(minutes * 6 ) ;
        canvas.drawLine(0, 10, 0, -100, mPaint);
        canvas.restore() ;
        //      
        canvas.save() ;
        mPaint.setStrokeWidth(1);
        canvas.rotate(seconds * 6 );
        System.out.println("seconds:" + seconds);
        canvas.drawLine(0, 10, 0, -120, mPaint) ;
        canvas.restore() ;
        //     
        canvas.save() ;
        mPaint.setStrokeWidth(3);
        canvas.drawCircle(0, 0, 2, mPaint);
        canvas.restore() ;
        //    
        postInvalidateDelayed(1000) ;
    }
}

OK、この簡単な例はこれで終わります.
ソースのダウンロード