<li id="34b3z"></li>
    <nav id="34b3z"></nav>
  1. <wbr id="34b3z"><legend id="34b3z"></legend></wbr>
    
    

        1. <form id="34b3z"></form>
          <sub id="34b3z"><table id="34b3z"><th id="34b3z"></th></table></sub>

          Android自定義View實例AnalogClock源碼

          [來源] 達內    [編輯] 達內   [時間]2012-12-05

          針對Android底層View的直接構造很多網友沒有實戰經驗,本次Android開發網結合目前平臺開源代碼一起通過AnalogClock類 來理解View的直接繼承。AnalogClock就是Home Screen上的那個帶有兩根指針的表盤類

            針對Android底層View的直接構造很多網友沒有實戰經驗,本次Android開發網結合目前平臺開源代碼一起通過AnalogClock類 來理解View的直接繼承。AnalogClock就是Home Screen上的那個帶有兩根指針的表盤類。它的實現我們直接從開源代碼可以了解到:

            public class AnalogClock extends View {

            private Time mCalendar;

            private Drawable mHourHand; //時針

            private Drawable mMinuteHand; //分針

            private Drawable mDial; //表盤背景

            private int mDialWidth; //表盤寬度

            private int mDialHeight; //表盤高度

            private boolean mAttached; //附著狀態

            private final Handler mHandler = new Handler(); //定一個Handler類實現更新時間

            private float mMinutes;

            private float mHour;

            private boolean mChanged; //時間是否改變

            public AnalogClock(Context context) {

            this(context, null);

            }

            public AnalogClock(Context context, AttributeSet attrs) {

            this(context, attrs, 0);

            }

            public AnalogClock(Context context, AttributeSet attrs,

            int defStyle) {

            super(context, attrs, defStyle);

            Resources r = mContext.getResources();

            TypedArray a =

            context.obtainStyledAttributes(

            attrs, com.android.internal.R.styleable.AnalogClock, defStyle, 0);

            mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial); //加載表盤資源

            if (mDial == null) {

            mDial = r.getDrawable(com.android.internal.R.drawable.clock_dial);

            }

            mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour); //加載時針圖片資源

            if (mHourHand == null) {

            mHourHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_hour);

            }

            mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute); //加載分針圖片

            if (mMinuteHand == null) {

            mMinuteHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_minute);

            }

            mCalendar = new Time(); //獲取當前系統時間

            mDialWidth = mDial.getIntrinsicWidth(); //獲取表盤圖片的寬度

            mDialHeight = mDial.getIntrinsicHeight(); //高度,同上

            }

            @Override

            protected void onAttachedToWindow() {

            super.onAttachedToWindow();

            if (!mAttached) {

            mAttached = true;

            IntentFilter filter = new IntentFilter(); //注冊一個消息過濾器,獲取時間改變、時區改變的action

            filter.addAction(Intent.ACTION_TIME_TICK);

            filter.addAction(Intent.ACTION_TIME_CHANGED);

            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);

            getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);

            }

            mCalendar = new Time();

            onTimeChanged();

            }

            @Override

            protected void onDetachedFromWindow() {

            super.onDetachedFromWindow();

            if (mAttached) {

            getContext().unregisterReceiver(mIntentReceiver); //反注冊消息過濾器

            mAttached = false;

            }

            }

            @Override

            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 != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {

            hScale = (float) widthSize / (float) mDialWidth;

            }

            if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {

            vScale = (float )heightSize / (float) mDialHeight;

            }

            float scale = Math.min(hScale, vScale);

            setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),

            resolveSize((int) (mDialHeight * scale), heightMeasureSpec));

            }

            @Override

            protected void onSizeChanged(int w, int h, int oldw, int oldh) {

            super.onSizeChanged(w, h, oldw, oldh);

            mChanged = true;

            }

            主要的繪圖重寫View的onDraw方法,我們可以看到通過canvas實例直接屏幕

            @Override

            protected void onDraw(Canvas canvas) {

            super.onDraw(canvas);

            boolean changed = mChanged;

            if (changed) {

            mChanged = false;

            }

            int availableWidth = mRight - mLeft;

            int availableHeight = mBottom - mTop;

            int x = availableWidth / 2;

            int y = availableHeight / 2;

            final Drawable dial = 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, x, y);

            }

            if (changed) {

            dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));

            }

            dial.draw(canvas);

            canvas.save();

            canvas.rotate(mHour / 12.0f * 360.0f, x, y); //計算時針旋轉的角度,android123提示就是那個時針圖片的旋轉角度,直接反應的就是表盤上那個針的時間

            final Drawable hourHand = mHourHand;

            if (changed) {

            w = hourHand.getIntrinsicWidth();

            h = hourHand.getIntrinsicHeight();

            hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));

            }

            hourHand.draw(canvas);

            canvas.restore();

            canvas.save();

            canvas.rotate(mMinutes / 60.0f * 360.0f, x, y); //同理,分針旋轉的角度

            final Drawable minuteHand = mMinuteHand;

            if (changed) {

            w = minuteHand.getIntrinsicWidth();

            h = minuteHand.getIntrinsicHeight();

            minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));

            }

            minuteHand.draw(canvas);

            canvas.restore();

            if (scaled) {

            canvas.restore();

            }

            }

            private void onTimeChanged() { //獲取時間改變,計算當前的時分秒

            mCalendar.setToNow();

            int hour = mCalendar.hour;

            int minute = mCalendar.minute;

            int second = mCalendar.second;

            mMinutes = minute + second / 60.0f;

            mHour = hour + mMinutes / 60.0f;

            mChanged = true;

            }

            private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { //監聽獲取時間改變action

            @Override

            public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {

            String tz = intent.getStringExtra("time-zone");

            mCalendar = new Time(TimeZone.getTimeZone(tz).getID());

            }

            onTimeChanged(); //獲取新的時間

            invalidate(); //刷新屏幕,強制類調用onDraw方法實現分針時針的走動

            }

            };

            看了本例根據,Android開發很簡單吧,感興趣的網友可以為本程序加入一個秒針,不過Android123提醒網友的是可能對于電池,以及系統運行效 率產生一定的影響,不過作為練習大家可以試一試。

          資源下載

          ?