Android TV利用viewPager實現輪播圖,並通過handler進行邏輯控制
阿新 • • 發佈:2018-12-15
公司要求實現一個輪播圖,滾動圖片及其對應文字。共有五張圖,包含小圓點。
最初的實現是參考了https://blog.csdn.net/zhaoxiaojian1213/article/details/78280132,使用ViewPager實現,新開一個執行緒去開啟輪播,並在其中控制跳向下一張圖。給viewPager設定OnPageChangeListener,來控制小圓點的變化。在Adapter中重寫的getCount方法中設定return Integer.MAX_VALUE;實現偽無限迴圈。除資料部分是動態獲取的,大致思路與連結中相似。但是這樣做有一些問題:輪播只有在Activity銷燬的時候才可以停止,不可以手動根據需求控制其停止與播放。
現在增加如下的需求:當焦點位於輪播圖內時,禁用輪播,可以左右鍵控制圖片的切換;當輪播圖位於第五張時(總共五張),按下右鍵之後跳轉到右邊的ListView上,並且開啟輪播;在輪播圖內按下鍵,焦點會到下方的TextView上,且也會開啟輪播(這兩句的意思也就是說焦點在輪播圖以外需要開啟輪播);當輪播圖位於第一張時,禁用左鍵切換圖片。
之後根據組長的建議修改了實現的方法:不開啟執行緒,而是重寫dispatchKeyEvent方法,在其中判斷對應的狀態,分別sendEmptyMessage和removeMessages,在Handler中進行控制。關鍵程式碼如下:
//viewPager是輪播圖,text_right是ListView推薦位,e1是下方的TextView @Override public boolean dispatchKeyEvent(KeyEvent event) { int flag = viewPager.getCurrentItem(); // 不響應按鍵彈起動作 if (event.getAction() != KeyEvent.ACTION_UP) { if (viewPager.hasFocus()) { // 輪播圖位於第五張圖時,再次按右鍵跳到右邊的推薦,並開啟輪播 if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT & flag % 5 == 4) { uiHandler.removeMessages(MSG_START_PPT); text_right.requestFocus(); // 始終跳到第一個推薦位 text_right.setSelection(0); uiHandler.sendEmptyMessage(MSG_START_PPT); return true; } // 焦點在輪播圖時,按下鍵跳到下方的按鈕,並開啟輪播 if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) { e1.requestFocus(); uiHandler.sendEmptyMessage(MSG_START_PPT); } // 輪播圖位於第一張圖時,按左鍵無響應 if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT & flag % 5 == 0) { uiHandler.removeMessages(MSG_START_PPT); return true; } } } // 不響應按鍵按下動作 if (event.getAction() != KeyEvent.ACTION_DOWN) { // 焦點位於輪播圖時,輪播圖停止輪播 if (viewPager.hasFocus()) { uiHandler.removeMessages(MSG_START_PPT); } } return super.dispatchKeyEvent(event); }
static final int MSG_START_PPT = 1; Handler uiHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_START_PPT: viewPager.setCurrentItem(viewPager.getCurrentItem() + 1); sendEmptyMessageDelayed(MSG_START_PPT, 5000); break; default: break; } }; };
比較有趣的一點是關於dispatchKeyEvent的。在遙控器按下和鬆開時分別會分發一次。可以設定判斷event.getAction() != KeyEvent.ACTION_UP和DOWN來遮蔽其中的一種,再在裡面寫邏輯,實現的效果是不一樣的。