Android TV屏 開發、RecyclerView焦點處理等

来源:https://www.cnblogs.com/LiuZhen/archive/2023/09/01/17671196.html
-Advertisement-
Play Games

TV屏使用遙控器控制,通過焦點操作界面,就跟電視投屏類似 一共兩個核心,焦點的處理,按鍵的監聽處理 按鍵原生提供了onKeyDown 來監聽,通過不同的 keyCode 區分不同的按鍵 一般如果沒有遙控器,可以通過電腦鍵盤測試,使用投屏軟體投屏後,對鍵盤按鍵效果跟遙控器類似 有時候沒有實體按鍵(比如 ...


TV屏使用遙控器控制,通過焦點操作界面,就跟電視投屏類似

一共兩個核心,焦點的處理,按鍵的監聽處理

按鍵原生提供了onKeyDown 來監聽,通過不同的 keyCode 區分不同的按鍵

一般如果沒有遙控器,可以通過電腦鍵盤測試,使用投屏軟體投屏後,對鍵盤按鍵效果跟遙控器類似

有時候沒有實體按鍵(比如電腦沒有返回鍵等),可以直接使用 adb 命令控制

adb shell input keyevent keyCode

至於長按事件,通過監聽的 KeyEvent 參數中 repeatCount 判斷,這裡最好等於某個數字時觸發,防止多次重覆觸發

主動獲取焦點使用方法 requestFocus(),但是可能會失敗,所以需要註意等待UI刷新完後在調用

並且在需要獲取焦點的view中設置屬性,否則沒法落焦

android:focusable="true"
android:focusableInTouchMode="true"

如果實在沒法控制刷新後的時機,那就只能延遲(postDelayed)獲取了,這個萬能鑰匙,但是儘量少用,影響效率,減低體驗

對於焦點,上面的只是基本操作,實際開發中吭比較多,比較如果界面複雜,焦點是很不好控制的,加上列表各種刷新,跨界面恢復焦點等,懂得都懂

所以為了更好的定位問題,需要藉助一些系統監聽來獲取焦點的狀態,才能知道問題在哪

比如可以重寫 requestChildFocus 方法,每次獲取焦點時列印信息,看看是否被其它 view 搶占焦點

override fun requestChildFocus(child: View?, focused: View?) {
        child?.let {
            val position = getChildViewHolder(child).absoluteAdapterPosition
            Logger.d("requestChildFocus $position ")
        }
    }

或者使用全局監聽 decorView.viewTreeObserver.addOnGlobalFocusChangeListener ,判斷哪些 view 獲取了焦點

針對獲取焦點無效怎麼處理?

估計很多時候會發現,調用了 requestFocus 方法沒反應,這是因為沒有對上個 view 的焦點進行 clear

你需要在監聽中,把獲取焦點的 view 賦值給你定義的變數 lastFocusView,然後每次調用 requestFocus 前先調用 lastFocusView.clearFocus()

tab 或者 列表 切換界面,這個時候操作遙控器子頁面自動搶占了焦點,怎麼處理?

可以通過對 onKeyDown 事件的攔截(return true),這樣子頁面是無法響應按鍵事件的,也就無法獲取焦點

針對一些個別 view 可以設置屏蔽焦點的屬性

android:focusable="false"
android:focusableInTouchMode="false"

焦點邊框樣式統一處理

可以通過全局監聽 addOnGlobalFocusChangeListener ,對 view 進行統一繪製邊框,或者一些邏輯控制等

window.decorView.viewTreeObserver
            .addOnGlobalFocusChangeListener { oldFocus, newFocus ->
                (newFocus ?: window.decorView.findFocus())?.let {
                    mainUpView.setFocusView(newFocus, oldFocus, 1.0f)
                }
            }

彈框無法獲取焦點怎麼處理?

一般 dialog 等只要設置了 focus 屬性,然後在初始化調用 requestFocus,是沒問題的,但是不排除一些個別情況

比如 PopupWindow,因為 window 彈出後,activity 的 onKeyDown 會無法響應,所以需要單獨監聽,前提是獲取到焦點

如果碰到焦點不好處理,或者落焦後繪製邊框等不方便,這裡建議手動控制,因為落焦繪製是統一在全局監聽里處理的,window 上需要額外監聽,沒有對這塊邏輯封裝好,就表示需要把整套邏輯搬到 window 上處理,這顯然很冗餘

所以何不直接監聽 onKeyDown ,然後通過代碼手動繪製邊框焦點

contentView.apply {
            requestFocus()
            binding.flMove.setOnKeyListener { _, keyCode, _ ->
                Logger.d("setOnKeyListener keyCode $keyCode")
                when (keyCode) {
                    KeyCode.KEYCODE_DPAD_LEFT -> {
                        switchMenu(1)
                    }

                    KeyCode.KEYCODE_DPAD_RIGHT -> {
                        switchMenu(0)
                    }

                    KeyCode.KEYCODE_BACK -> {
                        dismiss()
                    }
                }
                false
            }
        }

如果不太喜歡這個方案,還有另外一個方案

可以在xml中添加佈局,去仿造彈框,這樣焦點就可以統一處理,不過需要對這個佈局進行一些顯示隱藏的操作


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • **內核版本5.4** 在使用spi匯流排接上了一個小網卡,實現了我們開發板對網路的訪問之後,我還想接一個小的[spi屏幕 1.44寸款](https://item.taobao.com/item.htm?spm=a1z09.2.0.0.731e2e8dAkrB01&id=571409957622&_ ...
  • 本文旨在探討進程間通信的重要性,並介紹了不同的通信機制,如管道、消息隊列、共用記憶體、信號量、信號和套接字。通過理解這些通信機制的特點和應用場景,可以更好地實現進程間的高效數據共用。同時,本文還強調了同步和互斥機制的重要性,以確保數據的一致性和正確性。最後,還介紹了套接字作為一種跨網路和同一主機上進程... ...
  • linux主要目錄詳解 這裡首先說一句:Linux一切皆文件,即Linux世界中的所有、任意、一切東西都可以通過文件的方式訪問、管理。 /bin 系統有很多放置可執行文件的目錄, 但/bin比較特殊。 因為/bin放置的是在單人維護模式下還能夠被操作的指令。 在/bin下麵的指令可以被root與一般 ...
  • 什麼是GTID? GTID (Global Transaction ID) 是對於一個已提交事務的編號,並且是一個全局唯一的編號。 GTID 實際上 是由UUID+TID 組成的。其中 UUID 是一個 MySQL 實例的唯一標識。TID代表了該實例上已經提交的事務數量,並且隨著事務提交單調遞增。 ...
  • 設想一下,作為一個開發人員,你現在所在的公司有一套線上的 Hadoop 集群。A部門經常做一些定時的 BI 報表,B部門則經常使用軟體做一些臨時需求。那麼他們肯定會遇到同時提交任務的場景,這個時候到底應該如何分配資源滿足這兩個任務呢?是先執行A的任務,再執行B的任務,還是同時跑兩個? 如果你存在上述 ...
  • 從Oracle 10g 開始,Oracle提供了鎖定/解鎖表統計信息功能,它的目的是阻止資料庫自動收集統計信息,防止可能會產生/出現的糟糕的計劃。它對於數據頻繁更改的Volatile Tables最有用,因為Volatile Tables的某些數據集可能會生成糟糕的計劃。 官方的介紹如下: Prev ...
  • 我喜歡Kusto (或商用版本 Azure Data Explorer,簡稱 ADX) 是大家可以有目共睹的,之前還專門寫過這方面的書籍,請參考 [大數據分析新玩法之Kusto寶典](https://kusto.book.xizhang.com), 很可能在今年還會推出第二季,正在醞釀題材和場景中。 ...
  • 本章詳細指導了你如何安裝 HarmonyOS SDK、配置開發環境、創建 HarmonyOS 項目。現在,你已經準備好開始 HarmonyOS 開發了。 ...
一周排行
    -Advertisement-
    Play Games
  • WPF本身不支持直接的3D繪圖,但是它提供了一些用於實現3D效果的高級技術。 如果你想要在WPF中進行3D繪圖,你可以使用兩種主要的方法: WPF 3D:這是一種在WPF應用程式中創建3D圖形的方式。WPF 3D提供了一些基本的3D形狀(如立方體、球體和錐體)以及一些用於控制3D場景和對象的工具(如 ...
  • 一、XML概述 XML(可擴展標記語言)是一種用於描述數據的標記語言,旨在提供一種通用的方式來傳輸和存儲數據,特別是Web應用程式中經常使用的數據。XML並不預定義標記。因此,XML更加靈活,並且可以適用於廣泛的應用領域。 XML文檔由元素(element)、屬性(attribute)和內容(con ...
  • 從今年(2023)三月份開始,Github開始強制用戶開啟兩步驗證2FA(雙因數)登錄驗證,毫無疑問,是出於安全層面的考慮,畢竟Github賬號一旦被盜,所有代碼倉庫都會毀於一旦,關於雙因數登錄的必要性請參見:別讓你的伺服器(vps)淪為肉雞(ssh暴力破解),密鑰驗證、雙向因數登錄值得擁有。 雙因 ...
  • 第一題 下列代碼輸入什麼? public class Test { public static Test t1 = new Test(); { System.out.println("blockA"); } static { System.out.println("blockB"); } publi ...
  • 本文主要涉及的問題:用ElementTree和XPath讀寫XML文件;解決ElementTree新增元素後再寫入格式不統一的問題;QTableWidget單元格設置控制項 ...
  • QStandardItemModel 類作為標準模型,主打“類型通用”,前一篇水文中,老周還沒提到樹形結構的列表,本篇咱們就好好探討一下這貨。 還是老辦法,咱們先做示例,然後再聊知識點。下麵這個例子,使用 QTreeView 組件來顯示數據,使用的列表模型比較簡單,只有一列。 #include <Q ...
  • 一、直充內充(充值方式) 直充: 包裝套餐直接充值到上游API系統。【PID/Smart】 (如:支付寶、微信 話費/流量/語音/簡訊 等 充值系統)。 內充(套餐打包常見物聯卡系統功能): 套餐包裝 適用於不同類型套餐 如 流量、簡訊、語音 等。 (目前已完善流量邏輯) 二、套餐與計費產品 計費產 ...
  • 在前面幾天中,我們學習了Dart基礎語法、可迭代集合,它們是Flutter應用研發的基本功。今天,我們繼續學習Flutter應用另一個必須掌握知識點:非同步編程(即Future和async/await)。它類似於Java中的FutureTask、JavaScript中的Promise。它是後續Flut... ...
  • 針對改動範圍大、影響面廣的需求,我通常會問上線了最壞情況是什麼?應急預案是什麼?你帶開關了嗎?。當然開關也是有成本的,接下來本篇跟大家一起交流下高頻發佈支撐下的功能開關技術理論與實踐結合的點點滴滴。 ...
  • 1.d3.shuffle D3.shuffle() 方法用於將數組中的元素隨機排序。它使用 Fisher–Yates 洗牌演算法,該演算法是無偏的,具有最佳的漸近性能(線性時間和常數記憶體)。 D3.shuffle() 方法的語法如下: d3.shuffle(array, [start, end]) 其中 ...