如何自定义模拟时钟[关闭]

Posted

技术标签:

【中文标题】如何自定义模拟时钟[关闭]【英文标题】:how to customize an analog clock [closed] 【发布时间】:2012-05-22 17:32:35 【问题描述】:

我想在屏幕上显示四个自定义时钟我尝试使用此代码

/**
 * 
 * This widget display an analogic clock with two hands for hours and
 * 
 * minutes.
 */

@RemoteView
public class AnalogClock2 extends View 

    public AnalogClock2(Context context) 

        super(context);

        // TODO Auto-generated constructor stub

    

    private Time mCalendar;

    private Drawable mHourHand;

    private Drawable mMinuteHand;

    private Drawable mSecondHand;

    private Drawable mDial;

    private int mDialWidth;

    private int mDialHeight;

    private boolean mAttached;

    private final Handler mHandler = new Handler();

    private float mMinutes;

    private float mHour;

    private boolean mChanged;

    Context mContext;
    public static  String  mtimezone="Asia/Calcutta";
    public AnalogClock2(Context context, AttributeSet attrs) 

        this(context, attrs, 0);

    

    public AnalogClock2(Context context, AttributeSet attrs,

    int defStyle) 

        super(context, attrs, defStyle);

        Resources r = context.getResources();

    //  TypedArray a =

    //  context.obtainStyledAttributes(

    //  attrs, R.styleable.AnalogClock, defStyle, 0);

        mContext = context;

        // mDial =
        // a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);

        // if (mDial == null) 

        mDial = r.getDrawable(R.drawable.widgetdial);

        // 

        // mHourHand =
        // a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);

        // if (mHourHand == null) 

        mHourHand = r.getDrawable(R.drawable.widgethour);

        // 

        // mMinuteHand =
        // a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);

        // if (mMinuteHand == null) 

        mMinuteHand = r.getDrawable(R.drawable.widgetminute);

        mSecondHand = r.getDrawable(R.drawable.widgetminute);

        // 

        mCalendar = new Time();

        mDialWidth = mDial.getIntrinsicWidth();

        mDialHeight = mDial.getIntrinsicHeight();

    
    public static void timezone(String timezone)
          mtimezone=timezone;
    

    @Override
    protected void onAttachedToWindow() 

        super.onAttachedToWindow();

        if (!mAttached) 

            mAttached = true;

            IntentFilter filter = new IntentFilter();

            filter.addAction(Intent.ACTION_TIME_TICK);

            filter.addAction(Intent.ACTION_TIME_CHANGED);

            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);

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

        

        // NOTE: It's safe to do these after registering the receiver since the
        // receiver always runs

        // in the main thread, therefore the receiver can't run before this
        // method returns.

        // The time zone may have changed while the receiver wasn't registered,
        // so update the Time

        //mCalendar = new Time();
        mCalendar = new Time(mtimezone);
        // Make sure we update to the current time

        onTimeChanged();

        counter.start();

    

    @Override
    protected void onDetachedFromWindow() 

        super.onDetachedFromWindow();

        if (mAttached) 

            counter.cancel();

            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;

        

        System.out.println("***********************HAI****************");

        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;

    

    @Override
    protected void onDraw(Canvas canvas) 

        super.onDraw(canvas);

        // // here changes on every tick//////

        // / ////

        // / //

        // //////

        // // ///

        // //

        boolean changed = mChanged;

        if (changed) 

            mChanged = false;

        

        boolean seconds = mSeconds;

        if (seconds) 

            mSeconds = false;

        

        int availableWidth = 100;

        int availableHeight = 200;

        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);

        final Drawable hourHand = mHourHand;

        if (changed) 

            w = hourHand.getIntrinsicWidth();

            h = hourHand.getIntrinsicHeight();

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

        

        hourHand.draw(canvas);

        canvas.restore();

        canvas.save();

        canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);

        // canvas.rotate(mSecond, x, y);

        final Drawable minuteHand = mMinuteHand;

        if (changed) 

            w = minuteHand.getIntrinsicWidth();

            h = minuteHand.getIntrinsicHeight();

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

        

        minuteHand.draw(canvas);

        canvas.restore();

        canvas.save();

        canvas.rotate(mSecond, x, y);

        // minuteHand = mMinuteHand;

        if (seconds) 

            w = mSecondHand.getIntrinsicWidth();

            h = mSecondHand.getIntrinsicHeight();

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

        

        mSecondHand.draw(canvas);

        canvas.restore();

        if (scaled) 

            canvas.restore();

        

    

    MyCount counter = new MyCount(10000, 1000);

    public class MyCount extends CountDownTimer 

        public MyCount(long millisInFuture, long countDownInterval) 

            super(millisInFuture, countDownInterval);

        

        @Override
        public void onFinish() 

            counter.start();

        

        @Override
        public void onTick(long millisUntilFinished) 

            mCalendar.setToNow();

            int hour = mCalendar.hour;

            int minute = mCalendar.minute;

            int second = mCalendar.second;

            mSecond = 6.0f * second;

            mSeconds = true;

            // mChanged = true;

            AnalogClock2.this.invalidate();

            // Toast.makeText(mContext, "text", Toast.LENGTH_LONG).show();

        

    

    boolean mSeconds = false;

    float mSecond = 0;

    private void onTimeChanged() 

        mCalendar.setToNow();

        int hour = mCalendar.hour+4;

        int minute = mCalendar.minute+15;

        int second = mCalendar.second;

        mMinutes = minute + second / 60.0f;

        mHour = hour + mMinutes / 60.0f;

        mChanged = true;

    

    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 

        @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());

            
            mCalendar = new Time(mtimezone);
            onTimeChanged();

            invalidate();

        

    ;


【问题讨论】:

发布需求和一大段代码并不构成问题。 有什么问题?你有任何错误吗?如果没有,发生了什么? 没有看到你的评论@Corbin 这是在布局上显示单个模拟时钟,我想在布局上显示四个具有不同时区的模拟时钟 【参考方案1】:

@shivang 请参考此代码并放置四个时钟。如下代码。 希望对你有帮助。

private ImageView img;
 Handler mHandler;

 protected void onCreate(Bundle savedInstanceState) 
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  Thread myThread = null;

  Runnable runnable = new CountDownRunner();
  myThread = new Thread(runnable);
  myThread.start();

 

 public void doRotate() 

  runOnUiThread(new Runnable() 
   public void run() 
    try 

     Date dt = new Date();
     int hours = dt.getHours();
     int minutes = dt.getMinutes();
     int seconds = dt.getSeconds();
     String curTime = hours + ":" + minutes + "::" + seconds;
     Log.v("log_tag", "Log is here Time is now" + curTime);
     img = (ImageView) findViewById(R.id.imgsecond);
     RotateAnimation rotateAnimation = new RotateAnimation(
       (seconds - 1) * 6, seconds * 6,
       Animation.RELATIVE_TO_SELF, 0.5f,
       Animation.RELATIVE_TO_SELF, 0.5f);

     rotateAnimation.setInterpolator(new LinearInterpolator());
     rotateAnimation.setDuration(1000);
     rotateAnimation.setFillAfter(true);

     img.startAnimation(rotateAnimation);
     catch (Exception e) 

    
   
  );
 

 class CountDownRunner implements Runnable 
  // @Override
  public void run() 
   while (!Thread.currentThread().isInterrupted()) 
    try 

     doRotate();
     Thread.sleep(1000);
     catch (InterruptedException e) 
     Thread.currentThread().interrupt();
     catch (Exception e) 
     Log.e("log_tag", "Error is " + e.toString());
    
   
  
 

【讨论】:

以上是关于如何自定义模拟时钟[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

运行自定义“时钟”/ DateTime.now c#

如何在 QT5.6.1 中创建自定义按钮

如何在应用小部件中为 Android AnalogClock 设置时间?

如何在iPhone中创建带有小时和秒钟自定义图像的数字时钟?

在 Flutter 中创建自定义时钟小部件

Android 自定义时钟控件 时针分针秒针的绘制这一篇就够了