Android TV開發總結(三)構建一個TV app的焦點控制及遇到的坑

原文: Android TV開發總結(三)構建一個TV app的焦點控制及遇到的坑

版權聲明:我已委託「維權騎士」(rightknights.com)爲個人文章進行維權行動.轉載務必轉載全部,且須註明出處。不然保留追究法律責任 https://blog.csdn.net/hejjunlin/article/details/52835829

轉載請把頭部出處連接和尾部二維碼一塊兒轉載,本文出自逆流的魚yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829css

前言:上篇中,《Android TV開發總結(二)構建一個TV Metro界面(仿泰捷視頻TV版)》對應的源碼解析見《TV Metro界面(仿泰捷視頻TV版)源碼解析》一文,連接:http://blog.csdn.net/hejjunlin/article/details/52822499,github對應地址:https://github.com/hejunlin2013/TVSample,截至到當前發稿,已突破200star,若是喜歡的話,能夠star,也表示下支持,今天主要總結下TV開發中有焦點問題。android

在TV開發中沒有之前咱們phone端的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 事件來分發,而須要使用dispatchKeyEvent、onKeyDown、onKeyLisenter 等事件來分發處理焦點事件傳遞,並且TV端焦點沒有什麼好辦法能夠全局控制,須要咱們本身來想辦法規定焦點走向,能夠參考個人View焦點總結《Android View框架總結(二)View焦點》,本篇作應用場景補充說明及遇到有坑,看下Agenda:git

  • 採用Android自帶的直接控制焦點上下左右
  • 採用setOnFocusChangeListener控制焦點
  • adb按鍵派發控制焦點
  • 遇到的坑-遙控器按鍵失靈案列

Android TV 開發與通常Android開發最大的區別在於焦點控制 , 用戶在使用Android TV設備主要是經過遙控器操做app。焦點就是讓用戶知道的直接交互行爲。 然而一些app,依據系統對focus的判斷,會出現的情況: 上下導航時,不是想要的結果. 邊緣移動時,會出現焦點丟失的情況. 有時想直接定位到某個位置上.
android提供了一些焦點相關的屬性,在現有的框架層下經過設置View的屬性來得到焦點
github


這裏寫圖片描述

下面列出三種方法處理焦點問題

1、採用Android自帶的直接控制焦點上下左右的方法

採用Android自帶的直接控制焦點上下左右的方法web

所以在進行佈局時有必需要經過view.setId(…)指定view的特定ID,而後經過view.setNextLeftView(…)等四個方法控制該view的上下左右移動後所到達的view。然而這種方法只適用於前提就設置好ID的場景,不適合動態佈局的場景。 shell

看以下一段佈局:
微信


這裏寫圖片描述

rg_a1,rg_a2,rg_a3,rg_a4實際業務中會寫明其含義,而不是a1,a2之類,這裏只是爲介紹,這個自定義的MyCustomButton,按遙控器左鍵時,將找id爲rg_a1的view,焦點跳過去,按遙控器右鍵時,將找id爲rg_a2的view,焦點跳過去,按遙控器下鍵時,將找id爲rg_a3的view,焦點跳過去,按遙控器上鍵時,將找id爲rg_a5的view,焦點跳過去。

2、採用setOnFocusChangeListener控制焦點

看以下一段代碼:
markdown


這裏寫圖片描述

當OnFocusChangeListener時,就是從一個焦點跳到另外一個view上的變化過程。

3、adb按鍵派發控制焦點

按鍵的派發須瞭解一此KeyCode,下面是平時用到的主要的一些方向鍵:
app


這裏寫圖片描述

在按鍵過程當中 按下和鬆開的Action主要是ACTION_DOWN、ACTION_UP事件分發和處理是在ACTION_DOWN中處理

當設置View.setFocusable(true); 改變控件是否能夠得到焦點,然而同時會觸發 setOnFocusChangeListener事件框架

在adb中,能夠經過注入的方式模擬按鍵,如 adb shell input keyevent 3 給示模擬Home鍵
如下是的KEYCODE供參考:

KEYCODE_UNKNOWN=0;
KEYCODE_SOFT_LEFT=1;
KEYCODE_SOFT_RIGHT=2;
KEYCODE_HOME=3;
KEYCODE_BACK=4;
KEYCODE_CALL=5;
KEYCODE_ENDCALL=6;
KEYCODE_0=7;
KEYCODE_1=8;
KEYCODE_2=9;
KEYCODE_3=10;
KEYCODE_4=11;
KEYCODE_5=12;
KEYCODE_6=13;
KEYCODE_7=14;
KEYCODE_8=15;
KEYCODE_9=16;
KEYCODE_STAR=17;
KEYCODE_POUND=18;
KEYCODE_DPAD_UP=19;
KEYCODE_DPAD_DOWN=20;
KEYCODE_DPAD_LEFT=21;
KEYCODE_DPAD_RIGHT=22;
KEYCODE_DPAD_CENTER=23;
KEYCODE_VOLUME_UP=24;
KEYCODE_VOLUME_DOWN=25;
KEYCODE_POWER=26;
KEYCODE_CAMERA=27;
KEYCODE_CLEAR=28;
KEYCODE_A=29;
KEYCODE_B=30;
KEYCODE_C=31;
KEYCODE_D=32;
KEYCODE_E=33;
KEYCODE_F=34;
KEYCODE_G=35;
KEYCODE_H=36;
KEYCODE_I=37;
KEYCODE_J=38;
KEYCODE_K=39;
KEYCODE_L=40;
KEYCODE_M=41;
KEYCODE_N=42;
KEYCODE_O=43;
KEYCODE_P=44;
KEYCODE_Q=45;
KEYCODE_R=46;
KEYCODE_S=47;
KEYCODE_T=48;
KEYCODE_U=49;
KEYCODE_V=50;
KEYCODE_W=51;
KEYCODE_X=52;
KEYCODE_Y=53;
KEYCODE_Z=54;
KEYCODE_COMMA=55;
KEYCODE_PERIOD=56;
KEYCODE_ALT_LEFT=57;
KEYCODE_ALT_RIGHT=58;
KEYCODE_SHIFT_LEFT=59;
KEYCODE_SHIFT_RIGHT=60;
KEYCODE_TAB=61;
KEYCODE_SPACE=62;
KEYCODE_SYM=63;
KEYCODE_EXPLORER=64;
KEYCODE_ENVELOPE=65;
KEYCODE_ENTER=66;
KEYCODE_DEL=67;
KEYCODE_GRAVE=68;
KEYCODE_MINUS=69;
KEYCODE_EQUALS=70;
KEYCODE_LEFT_BRACKET=71;
KEYCODE_RIGHT_BRACKET=72;
KEYCODE_BACKSLASH=73;
KEYCODE_SEMICOLON=74;
KEYCODE_APOSTROPHE=75;
KEYCODE_SLASH=76;
KEYCODE_AT=77;
KEYCODE_NUM=78;
KEYCODE_HEADSETHOOK=79;
KEYCODE_FOCUS=80;//*Camera*focus
KEYCODE_PLUS=81;
KEYCODE_MENU=82;
KEYCODE_NOTIFICATION=83;
KEYCODE_SEARCH=84;
KEYCODE_MEDIA_PLAY_PAUSE=85;
KEYCODE_MEDIA_STOP=86;
KEYCODE_MEDIA_NEXT=87;
KEYCODE_MEDIA_PREVIOUS=88;
KEYCODE_MEDIA_REWIND=89;
KEYCODE_MEDIA_FAST_FORWARD=90;
KEYCODE_MUTE=91;


這裏寫圖片描述

  • 問題描述:播放中出現屏保,從屏保回到某頁面後,遙控器失靈。從某頁進入全屏播放,暫停,等小米的屏保出來後將屏保消失,返回到某頁面繼續播放。此時遙控器方向鍵、肯定鍵均無響應。Home鍵、電源鍵有響應。菜單鍵有響應。
    分析:沒有響應,按鍵被攔截,查了下當時改動的代碼時,對按鍵並未作特殊攔截…. 對比以前的版本,沒有這個問題。確認問題出如今浮層…從log中看,onWindowFocusChanged,在從h5界面/屏保界面回到某頁面,沒有被調用。
    說明從window到activity這層,按鍵就被吃掉了。


    這裏寫圖片描述

  • 接着分析:整個BaseActivity,沒有接收到Action_Down事件
    Log中打印的「Dropping event due to no window focus」,思路又斷了。
    繼續作對比,發現show出浮層時,沒有任何異常,可是隻要show時,焦點移動,就能復現按鍵不響應。最後就定位到一個自定義控件上


    這裏寫圖片描述

  • 再接着分析:這個控件1600多行代碼,最初一直在找以前版本改動的地方區別,以前版本主要是作一些對這個控件的定製化,其餘的先不考慮,排除法,找和event相關的方法。dispatchKeyEvent沒有任何異常,又沒有思路了,既然是系統級別的傳遞過程當中就被吃了,會不會和view相關,由於只要焦點移動,就失靈,焦點移動伴隨着,有一個popupwindow彈出,最終定位在onAttachWindow,好像也沒有作什麼特殊的事,用了一個getHandler,起初我覺得是個本身寫的方法,追點進去getHandler一看,是View的

    這裏寫圖片描述
  • 問題修復:
    總結:用View的Handler之前是爲處理popupwindow時,popupwindow經過post的方式去show,可是若是此時activity ondestory則會致使出錯,因此加了onDetachWindow和onAttachWindow,緣由主要是在onDetachWindow時,mHandler.removeCallbacksAndMessages(null);這句話致使,它至關因而把window發給View這層message給移除了。最後修改只移除它對應的的runnable,問題修復。

    這裏寫圖片描述

第一時間得到博客更新提醒,以及更多android乾貨,源碼分析,歡迎關注個人微信公衆號,掃一掃下方二維碼或者長按識別二維碼,便可關注。


這裏寫圖片描述
若是你以爲好,隨手點贊,也是對筆者的確定,也能夠分享此公衆號給你更多的人,原創不易
相關文章
相關標籤/搜索