<button id="u2w23"></button>

<tbody id="u2w23"><track id="u2w23"></track></tbody><dd id="u2w23"><track id="u2w23"></track></dd><button id="u2w23"><acronym id="u2w23"></acronym></button> <tbody id="u2w23"><noscript id="u2w23"></noscript></tbody>

  • <button id="u2w23"></button><li id="u2w23"><acronym id="u2w23"><cite id="u2w23"></cite></acronym></li>

  • 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提醒網友的是可能對于電池,以及系統運行效 率產生一定的影響,不過作為練習大家可以試一試。

    資源下載

    ?