Android TV開發(fā)按鍵與焦點深入分析(四)--實際使用的例子

前面三篇都是從源碼的角度分析按鍵事件雀久、焦點變換的原理隐圾,作為應用層的開發(fā)者必搞,
分析源碼都是帶著實際的開發(fā)困惑的偎快,要不然誰沒事做會read the fucking source code,
今天就分享一個Android TV開發(fā)中的解決的焦點移動問題入录。

起因

使用過奇異果TV應用的同學會發(fā)現(xiàn)它有焦點換行的功能蛤奥,就是當一直按遙控器右鍵時焦點View會換行到下一行的第一個View,如下


焦點換行

使用體驗很好僚稿,重要的是產(chǎn)品同學也覺得很好凡桥。

看到這個效果,我的第一直覺是給每個View設置Id蚀同,Id從左到右缅刽、從上到下增加,或者給每個View設置自增的Tag,每次都去尋找Id + 1或者Tag +1的View蠢络,然后讓它獲得焦點衰猛,這不就OK了。但這還是沒有優(yōu)雅的解決問題刹孔,只是把問題拋給了后臺啡省、運營,讓他們一個一個的設置運營位的編號。
那有沒有成本很小的解決方法呢卦睹?

getFocusedRect方法

上一篇的分析中我們知道當按鍵事件要轉(zhuǎn)換成焦點移動時畦戒,需要在眾多的View中尋找一個位置
最合適的View,然后讓它獲得焦點。而這個位置的依據(jù)是什么结序?其實就是每個View的getFocusedRect返回的Rect兢交,
對于當前有焦點的View,用這個返回的Rect計算它搜尋的起始位置笼痹;對于沒有焦點的View配喳,用
這個Rect來表示自己當前的位置。View的這個方法的代碼如下:

/**
  * When a view has focus and the user navigates away from it, the next view is searched for
  * starting from the rectangle filled in by this method.
  *
  * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
  * of the view.  However, if your view maintains some idea of internal selection,
  * such as a cursor, or a selected row or column, you should override this method and
  * fill in a more specific rectangle.
  *
  * @param r The rectangle to fill in, in this view's coordinates.
  */
 public void getFocusedRect(Rect r) {
     getDrawingRect(r);
 }

實際上默認返回的就是View的繪制區(qū)域凳干,但注釋也說了可以根據(jù)實際的需要自己修改晴裹,那我就有一些想法了:可以根據(jù)View在不同的位置返回不同的Rect

原理與實現(xiàn)

1.原理

  1. 對于有焦點的View救赐,如果它沒靠近屏幕的邊緣涧团,這個方法返回實際的繪制區(qū)域
  2. 對于有焦點的View,如果它靠近屏幕的右邊緣经磅,將這個Rect移動到下一行的左側(cè)屏幕的左外側(cè)泌绣,左邊緣的View同理
  3. 對于沒有焦點的View,這個方法返回實際的繪制區(qū)域

這樣當在右邊緣的View上按右鍵時预厌,實際上它的搜尋的起始位置在下一行的左外側(cè)阿迈,位置最合適的View就是下一行第一個View,這樣就可以花很小的代價解決這焦點換行的問題轧叽。

原理圖如下:

原理圖

當View在屏幕右邊緣時苗沧,將Focus Rect的top設置為自己的botom的位置、Rect的right設置為0炭晒,實際的搜索起始Rect是黑色虛線的Rect(原理可看上篇的分析)待逞,這樣最合適的獲得焦點的View就是第二行的第一個View,達到了換行的目的

2.實現(xiàn)

重寫View的getFocusedRect方法如下:

@Override
  public final void getFocusedRect(Rect r) {
      //如果有焦點
      if (isFocused()) {
          //獲得根View的繪制區(qū)域
          rootView.getDrawingRect(mRootViewRect);
          //獲得自己的繪制區(qū)域
          getDrawingRect(mTempDrawingRect);
          //轉(zhuǎn)換自己的繪制區(qū)域到根View的坐標系中去网严,方便計算FocusedRect的位置
          rootView.offsetDescendantRectToMyCoords(this, mTempDrawingRect);
          //判斷自己是否滿足換行的條件识樱,1)按右鍵 2)自己在屏幕的右邊緣
          if ((mTempDrawingRect.right + 20) > mRootViewRect.right && currentKeyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
              //重新獲取自己的位置
              getDrawingRect(mTempDrawingRect);
              //轉(zhuǎn)換根View的坐標系中去
              rootView.offsetDescendantRectToMyCoords(this, mTempDrawingRect);
              //將這個Rect移動到自己的下方、左側(cè)屏幕的左外側(cè)
              mTempDrawingRect.left = 0 - getMeasuredWidth();
              mTempDrawingRect.right = 0;
              mTempDrawingRect.bottom = mTempDrawingRect.bottom + getMeasuredHeight();
              mTempDrawingRect.top = mTempDrawingRect.top + getMeasuredHeight();
              //將focus rect的坐標系還原到自己的坐標系
              rootView.offsetRectIntoDescendantCoords(this, mTempDrawingRect);
              r.set(mTempDrawingRect);
          } else if (mTempDrawingRect.left - 20 < mRootViewRect.left && currentKeyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
              //左鍵同理
            ......
          } else {//沒有在左右邊緣或者沒有按對應的左右鍵
              super.getFocusedRect(r);
          }
      } else {//沒有焦點
          super.getFocusedRect(r);
      }
  }

大概的原理都寫在了代碼注釋中了震束,完整的代碼實現(xiàn)見FocusLineFeedFrameLayout.java

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怜庸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驴一,更是在濱河造成了極大的恐慌休雌,老刑警劉巖灶壶,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肝断,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機胸懈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門担扑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人趣钱,你說我怎么就攤上這事涌献。” “怎么了首有?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵燕垃,是天一觀的道長。 經(jīng)常有香客問我井联,道長卜壕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任烙常,我火速辦了婚禮轴捎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚕脏。我一直安慰自己侦副,他們只是感情好,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布驼鞭。 她就那樣靜靜地躺著秦驯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挣棕。 梳的紋絲不亂的頭發(fā)上汇竭,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天,我揣著相機與錄音穴张,去河邊找鬼细燎。 笑死,一個胖子當著我的面吹牛皂甘,可吹牛的內(nèi)容都是我干的玻驻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼偿枕,長吁一口氣:“原來是場噩夢啊……” “哼璧瞬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渐夸,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嗤锉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墓塌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘟忱,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡奥额,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了访诱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垫挨。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖触菜,靈堂內(nèi)的尸體忽然破棺而出九榔,到底是詐尸還是另有隱情,我是刑警寧澤涡相,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布哲泊,位于F島的核電站,受9級特大地震影響催蝗,放射性物質(zhì)發(fā)生泄漏攻旦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一生逸、第九天 我趴在偏房一處隱蔽的房頂上張望牢屋。 院中可真熱鬧,春花似錦槽袄、人聲如沸烙无。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽截酷。三九已至,卻和暖如春乾戏,著一層夾襖步出監(jiān)牢的瞬間迂苛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工鼓择, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留三幻,地道東北人。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓呐能,卻偏偏與公主長得像念搬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子摆出,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容