读书人

安卓札记:Handler【显示时间】

发布时间: 2013-04-26 16:27:53 作者: rapoo

安卓笔记:Handler【显示时间】



?

1.简单数字时钟
学习通过Handler +线程刷新UI,时钟或者计时器练习
下面这段简短的代码就可以实现(关键代码就只有Handler的post和postDelayed方法),其中的机制(消息队列等)还要继续学习

?

public class RefreshActivity extends Activity implements Runnable {private TextView tv;private Handler h = new Handler();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_refresh);tv = (TextView) findViewById(R.id.tv);h.post(this);/* * Handler的post方法  * final boolean post(Runnable r)  * Causes the Runnable r to be added to the message queue.  * 把RefreshActivity这个线程加到消息队列中 */}@Overridepublic void run() {// 线程体Date date = new Date(System.currentTimeMillis());SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String time = sdf.format(date);tv.setText(time);h.postDelayed(this, 1000);/* * Handler的postDelayed方法 * final boolean postDelayed(Runnable r, long delayMillis)  * Causes the Runnable r to be added to the message queue, to be run after the * specified amount of time elapses. *  * 把RefreshActivity这个线程延时1秒加入到消息队列 */}}

?

?

这个是常规的比较完整的写法了,比较容易理解

/** * 整个Activity开启一个UI主线程,负责子线程的管理、UI的更新 * */public class NewRefreshActivity extends Activity {private TextView tv;private Handler handler;private String time;private boolean isRunning = true;//用这个标志位来让线程不断运行下去@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_refresh);tv = (TextView) findViewById(R.id.tv);/** * Handler属于主线程,把子线程中传递过来的数据用来更新UI *  * Handler之所以存在,是因为子线程是不能够更改创建UI的线程中的UI的 * */handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);tv.setText(msg.obj   "");}};/** * 用来处理时间增长的子线程(匿名内部类) * 在这里让时间以1秒为单位增长,并把改变了的时间放到msg的obj属性中,通过Handler传给主线程  *  * */new Thread() {@Overridepublic void run() {super.run();while(isRunning){try {sleep(1000);//睡眠1秒Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");time = sdf.format(date);Message msg = new Message();msg.obj = time;handler.sendMessage(msg);} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}}

?

?

2.关于android自带时钟小工具
Android自带的只有时针和分针的AnalogClock,只要在上面的代码中初始化就能走了,为什么呢?



?

4.关于自定义时钟
把需要的图片资源都放到drawable中,在自定义的View(继承自View类)中,用BitmapDrawble加载图片,在线程中每隔秒就重绘秒针图片、60秒重绘分针图片、360秒重绘时针图片(关于重绘的位置,还有点复杂,感觉)
下载了一个筒子写的自定义时钟源码,没怎么明白,差不多就是这么个思路

?

?

@RemoteViewpublic class AnalogClock extends View {    private BitmapDrawable mDialDrawable;    private BitmapDrawable mHourHandDrawable;    private BitmapDrawable mMinuteHandDrawable;    private BitmapDrawable mSecondHandDrawable;        private int mDialWidth;    private int mDialHeight;        private boolean mAttached = false;        private float mHours;    private float mMinutes;    private float mSeconds;        private int totaltime;    /**     * 标志时间、时钟布局大小等是否有改变     */    private boolean mChanged;        /**     * 线程队列管理,消息传递和处理机制     */    private Handler loopHandler = new Handler();        /**     * 标志页面刷新线程尚未执行     */    private boolean isRun = false;        /**     * 时钟运行     */    private void run()    {    /**     * 将线程加入队列     */    loopHandler.post(tickRunnable);    }    private Runnable tickRunnable = new Runnable() {           public void run() {        /**         * 在非UI线程调用,强制刷新界面         */        postInvalidate();                totaltime++;        /**         * 将线程加入队列,1000毫秒后启动         */            loopHandler.postDelayed(tickRunnable, 1000);           }       };   /** * 构造方法 */    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);        totaltime = 0;                Resources r = this.getContext().getResources();InputStream is =null;/** * 初始化表盘,时针,分针, 秒针 */is = r.openRawResource(R.drawable.clockdroid2_dial);mDialDrawable = new BitmapDrawable(is);is = r.openRawResource(R.drawable.clockdroid2_hour);mHourHandDrawable = new BitmapDrawable(is);is = r.openRawResource(R.drawable.clockdroid2_minute);mMinuteHandDrawable = new BitmapDrawable(is);is = r.openRawResource(R.drawable.clockdroid2_second);mSecondHandDrawable = new BitmapDrawable(is);        /**         * 获取表盘有效像素宽高         */        mDialWidth = mDialDrawable.getIntrinsicWidth();        mDialHeight = mDialDrawable.getIntrinsicHeight();    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        if (!mAttached) {            mAttached = true;            IntentFilter filter = new IntentFilter();            filter.addAction(Intent.ACTION_TIME_CHANGED);            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);            getContext().registerReceiver(mIntentReceiver, filter, null, loopHandler);        }    }    @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;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if(!isRun)        {        run();        isRun = true;        return;        }        onTimeChanged();        boolean changed = mChanged;        if (changed) {            mChanged = false;        }        int availableWidth = getWidth();        int availableHeight = getHeight();        int x = availableWidth / 2;        int y = availableHeight / 2;         final Drawable dial = mDialDrawable;        int w = dial.getIntrinsicWidth();        int h = dial.getIntrinsicHeight();        if (changed) {            dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));        }        dial.draw(canvas);        canvas.save();        canvas.rotate(mHours / 12.0f * 360.0f, x, y);        final Drawable hourHand = mHourHandDrawable;        if (changed) {            w = hourHand.getIntrinsicWidth();            h = hourHand.getIntrinsicHeight();            hourHand.setBounds(x - (w / 2), y - (h * 53 / 100), x + (w / 2), y + (h * 47 / 100));        }        hourHand.draw(canvas);        canvas.restore();        canvas.save();        canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);        final Drawable minuteHand = mMinuteHandDrawable;        if (changed) {            w = minuteHand.getIntrinsicWidth();            h = minuteHand.getIntrinsicHeight();            minuteHand.setBounds(x - (w / 2), y - (h * 53 / 100), x + (w / 2), y + (h * 47 / 100));        }        minuteHand.draw(canvas);        canvas.restore();        canvas.save();        canvas.rotate(mSeconds / 60.0f * 360.0f, x, y);        final Drawable scendHand = mSecondHandDrawable;        if (changed) {            w = scendHand.getIntrinsicWidth();            h = scendHand.getIntrinsicHeight();            scendHand.setBounds(x - (w / 2), y - (h * 53 / 100), x + (w / 2), y + (h * 47 / 100));        }        scendHand.draw(canvas);        canvas.restore();    }    private void onTimeChanged() {        mSeconds = totaltime % 60;        mMinutes = totaltime / 60;        mHours = totaltime / 3600;                mChanged = true;    }        private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            onTimeChanged();            invalidate();        }    };}

??

?

?



这个显示,貌似不正确,两个钟显示不一样,数字时钟就按12小时制也不是当前的时间

?

安卓札记:Handler【显示时间】

读书人网 >Android

热点推荐