• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 【安卓筆記】Handler:顯示時間



     

    1.簡單數字時鐘
    學習通過Handler +線程刷新UI,時鐘或者計時器練習
    下面這段簡短的代碼就可以實現(關鍵代碼就只有Handler的post和postDelayed方法),其中的機制(消息隊列等)還要繼續學習

     

    public class RefreshActivity extends Activity implements Runnable {
    	private TextView tv;
    	private Handler h = new Handler();
    
    	@Override
    	protected 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這個線程加到消息隊列中
    		 */
    	}
    
    	@Override
    	public 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;//用這個標志位來讓線程不斷運行下去
    
    	@Override
    	protected 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() {
    			@Override
    			public void handleMessage(Message msg) {
    				super.handleMessage(msg);
    					tv.setText(msg.obj   "");
    			}
    
    		};
    /**
     * 用來處理時間增長的子線程(匿名內部類)
     * 在這里讓時間以1秒為單位增長,并把改變了的時間放到msg的obj屬性中,通過Handler傳給主線程 
     * 
     * */
    		new Thread() {
    			@Override
    			public 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秒重繪時針圖片(關于重繪的位置,還有點復雜,感覺)
    下載了一個筒子寫的自定義時鐘源碼,沒怎么明白,差不多就是這么個思路

     

     

    @RemoteView
    public 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小時制也不是當前的時間

     

    版權聲明:本文為iteye_19057原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/iteye_19057/article/details/82486175

    智能推薦

    xamarin學習筆記A13(安卓Handler異步消息處理)

    (每次學習一點xamarin就做個學習筆記和視頻來加深記憶鞏固知識) 如有不正確的地方,請幫我指正。 安卓異步消息處理簡介   有時候需要執行一些耗時的操作,例如從遠程服務器讀取數據,讀取的時間的長度由很多因素決定,我們不希望主線程被阻塞程序無法進行其它工作,而且Android中只能在主線程進行UI操作,不能在子線程操作,如果要根據子線程執行的結果來更新UI時,這時就需要用到安...

    安卓開發使用Thread、Handler實時更新UI學習筆記。

    最近開發安卓的時候常有需求要實時更新UI,然后發現很多都忘了,故做個學習筆記。 首先,假設需求:點擊按鈕后實時更新當前時間。 然后開工! 布局代碼: Java代碼: 完畢。...

    安卓service筆記

    Android8.0 Service 今天照著書上和博客的教程去學習,結果發現各種報錯(如下圖)。就知道service在高版本Android中又有了新的規則,于是將今天的學習整理成筆記,方便日后復習。不過Android的每次更新,都一直在努力收緊應用權限。不過我覺得挺好的,開放的權限導致了很多安全問題和性能問題,權限上去了用戶體驗會好很多。 生命周期 從上圖可看到有兩種方法可以啟動Service,...

    安卓學習筆記

    學習安卓的學習筆記,留存一下,雖然以后可能都不會從事安卓相關的工作了,紀念一下。 1 Activity 1 返回棧 活動可以層疊,啟動一個新的活動會覆蓋在原活動上,Back會銷毀最上面的活動,下面的一個活動就會重新顯示。 用任務管理一系列活動。任務用返回棧描述。 啟動一個新的活動,這個活動就在返回棧中入棧,finish()即棧頂元素出棧,系統總是會顯示處于棧頂的活動給用戶。(所以finish()銷...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡