1. 程式人生 > >安卓機頂盒開發中的焦點之二

安卓機頂盒開發中的焦點之二

一,焦點相關Api說明

  • View中定義了一個方法,用來判斷View自身是否獲取到焦點或者其內部的子View是否獲取到焦點。
/**
 * Returns true if this view has focus itself, or is the ancestor of the
 * view that has focus.
 *
 * @return True if this view has or contains focus, false otherwise.
 */
@ViewDebug.ExportedProperty(category = "focus")
public boolean
hasFocus() { return (mPrivateFlags & PFLAG_FOCUSED) != 0; }
  • View中定義了一個isFocused方法,該方法用於判斷該View自身是否已經獲取到焦點。
/**
 * Returns true if this view has focus
 *
 * @return True if this view has focus, false otherwise.
 */
@ViewDebug.ExportedProperty(category = "focus")
public boolean isFocused() {
    return
(mPrivateFlags & PFLAG_FOCUSED) != 0; }
  • ViewGroup中定義了一個名為setDescendantFocusability的方法,該方法需要指定一個focusability,該值可以為三種類型:
FOCUS_BEFORE_DESCENDANTS:viewgroup會優先其子類控制元件而獲取到焦點
FOCUS_AFTER_DESCENDANTS:viewgroup只有當其子類控制元件不需要獲取焦點時才獲取焦點
FOCUS_BLOCK_DESCENDANTS:viewgroup會覆蓋子類控制元件而直接獲得焦點

二,介面初始化時系統如何標記初始焦點

  • ViewRootImpl類中有一個比較重要的方法performTraversals,該方法中有如下一段程式碼:
if (mFirst) {
    // handle first focus request
    if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: mView.hasFocus()="
            + mView.hasFocus());
    if (mView != null) {
        if (!mView.hasFocus()) {
            mView.requestFocus(View.FOCUS_FORWARD);
            if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: requested focused view="
                    + mView.findFocus());
        } else {
            if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: existing focused view="
                    + mView.findFocus());
        }
    }
}
  • handle first focus request意味著這裡處理第一次焦點的請求,注意這裡的mView其實就是DecorView,也就是位於view tree的最頂層的View。其本質就是一個FrameLayout,當自身或者其內部子View不包含焦點的時候,就會呼叫requestFocus嘗試標記焦點View。我們再來看下ViewGroup中重寫的requestFocus
/**
 * {@inheritDoc}
 *
 * Looks for a view to give focus to respecting the setting specified by
 * {@link #getDescendantFocusability()}.
 *
 * Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to
 * find focus within the children of this group when appropriate.
 *
 * @see #FOCUS_BEFORE_DESCENDANTS
 * @see #FOCUS_AFTER_DESCENDANTS
 * @see #FOCUS_BLOCK_DESCENDANTS
 * @see #onRequestFocusInDescendants(int, android.graphics.Rect)
 */
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
    if (DBG) {
        System.out.println(this + " ViewGroup.requestFocus direction="
                + direction);
    }
    int descendantFocusability = getDescendantFocusability();

    switch (descendantFocusability) {
        case FOCUS_BLOCK_DESCENDANTS:
            return super.requestFocus(direction, previouslyFocusedRect);
        case FOCUS_BEFORE_DESCENDANTS: {
            final boolean took = super.requestFocus(direction, previouslyFocusedRect);
            return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
        }
        case FOCUS_AFTER_DESCENDANTS: {
            final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
            return took ? took : super.requestFocus(direction, previouslyFocusedRect);
        }
        default:
            throw new IllegalStateException("descendant focusability must be "
                    + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
                    + "but is " + descendantFocusability);
    }
}
  • 我們注意到,這裡會根據getDescendantFocusability返回的結果,也就是會先判斷我們有沒有設定focusability,然後會根據型別首先判斷onRequestFocusInDescendants的返回值,如果為真就直接返回了。onRequestFocusInDescendants是個什麼鬼呢,接著看:
@SuppressWarnings({"ConstantConditions"})
protected boolean onRequestFocusInDescendants(int direction,
        Rect previouslyFocusedRect) {
    int index;
    int increment;
    int end;
    int count = mChildrenCount;
    if ((direction & FOCUS_FORWARD) != 0) {
        index = 0;
        increment = 1;
        end = count;
    } else {
        index = count - 1;
        increment = -1;
        end = -1;
    }
    final View[] children = mChildren;
    for (int i = index; i != end; i += increment) {
        View child = children[i];
        if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
            if (child.requestFocus(direction, previouslyFocusedRect)) {
                return true;
            }
        }
    }
    return false;
}
  • 我們注意到,其內部遍歷所有子View,當子View為可見時,就嘗試去標記焦點。因為onRequestFocusInDescendants方法為protected型別,所以我們通常可以重寫該方法做一些操作。

相關推薦

機頂盒開發焦點

一,焦點相關Api說明 View中定義了一個方法,用來判斷View自身是否獲取到焦點或者其內部的子View是否獲取到焦點。 /** * Returns true if this view

H5對WeView開發的影響

 1.body,或者html 高度為100% 會導致下拉直接觸發原生的重新整理控制元件,而不是webView滑動到頂部後重新整理,以及不會執行onScrollChanged 方法,並且getScrollY 總是返回0 ,getContentHeight * getScale 的值總是與webView

中高階開發面試知識點——快取

前言 幾乎所有的專案都做了快取,但是快取做的怎麼樣,其實只有我們自己知道。快取做的好,沒有網路也能流暢的使用;再多的資料請求都不會出現卡頓延遲等待很久的情況。 程式中除了圖片快取(三級快取),還有資訊快取。當用戶無法聯網時,app會預設顯示快取的資料。 前言快取方式 SQLite 下載完資料檔案後,

APP開發的螢幕適配問題如何解決?

通過使用”wrap_content”、”match_parent”和”weight”來替代硬編碼的方式定義檢視大小&位置,你的檢視要麼僅僅使用了需要的那邊一點空間,要麼就會充滿所有可用的空間,即按需佔據空間大小,能讓你的佈局元素充分適應你的螢幕尺寸。

Tv開發(一)移動智慧電視焦點控制(觸控事件)

      前言:移動智慧裝置的發展,推動了安卓另一個領域,包括智慧電視和智慧家居,以及可穿戴裝置的大量使用,但是這些裝置上的開發並不是和傳統手機開發一樣,特別是焦點控制和使用者操作體驗風格上有很大的區

工作碰到的那些坑()-混合開發webview開啟連結出錯

https%3a%2f%2fmapi.alipay.com%2fgateway.do%3f_input_charset%3dutf-8%26it_b_pay%3d1d%26notify_url%3dhttp%253A%252F%252Fpay.jz-test.ganji.com%252Fpay%252Fnot

如何在原生專案加入mui相關檔案進行開發(使用新版本5+SDK建立最簡Android原生工程(Android studio))

緣起 最近在搭一個android開發的demo,專案使用androidstudio作為開發工具,使用混合式開發,途中需要整合mui.但是網上找了很多教程都是老版本的,以至於MUI官網提供的demo已經不符合教程了。後來進過多方努力終於找到了新版的教程,特此記錄。 新版教程連結點這

【GT-應用開發長按儲存圖片】

前言:微信預覽圖片,長按會出現一個彈出框,其中會有一個“儲存圖片”。今天正好做了一個類似的小功能,特意寫了一個小demo來記錄一下。         首先,介紹一下該demo:主介面有一個ImageView顯示本人的微信二維碼,要實現的功能是長按二維碼彈出提示框,告知使用者

【GT-應用開發Glide獲取視訊縮圖】

前言:期待已久的週末終於到來了,雖然明天還需要上班,但是今天卻不像平日裡迫切的趕回家。飯後,閒來無事結合最近的一個專案需求,編寫一個小demo,主要是實現視訊檔案縮圖的獲取。         我的思路是,首先獲取所有的視訊檔案列表,然後依次獲取縮圖並展示。但是出於時間因素,

【GT-應用開發簡易文字廣告輪播】

前言:又是午休時間,今天寫一個簡單的文字輪播demo,主要由一個水平方向的TextView和一個豎直方向的ListView組成。安卓目前提供的TextView支援跑馬燈效果(修改幾個屬性即可),但是其有一個缺點就是一旦失去焦點,文字便不再滾動,自定義TextView修改幾個方

【GT-應用開發退出APP】

前言:目前在app中主流的退出應用的方式有兩種,一種是彈出提示框,另外一種則是主流的雙擊退出。今天整理了一下相關程式碼,編寫一個小demo整理了幾種退出方式。   在安卓中,監聽返回鍵有兩種方式,分別是onKeyDown與onBackPress,我定義四種實現方式如下:

-自定義佈局】App開發思路 一步一個腳印(十)實現內嵌在app的webview 騰訊開源X5 高效安全

實現內嵌在app中的webview 採用騰訊開源X5 高效安全 webview在app的使用中,十分頻繁,原生的webview載入速度相對來說很慢,而且很費流量。騰訊開源了x5的webview

奧比光招聘 --- 驅動開發工程師

工作地點:深圳 崗位職責: 1、負責android體感器裝置的驅動開發及維護,並必要時參與上層軟體開發; 2、與上層軟體開發人員共同制定驅動與上層軟體介面; 3、編寫相關設計文件。協同測試等部門解決研發、生產測試及量產過程中出現的軟體問題; 4、參與重大技術問題的技術攻關,提升軟體開發水平; 5、收集軟體使

實戰開發JNI從小白到偽老白深入瞭解JNI動態註冊native方法及JNI資料使用

前言 或許你知道了jni的簡單呼叫,其實不算什麼百度谷歌一大把,雖然這些jni絕大多數情況下都不會讓我們安卓工程師來弄,畢竟還是有點難,但是我們還是得打破砂鍋知道為什麼這樣幹吧,至少也讓我們知道呼叫流程和資料型別以及處理方法,或許你會有不一樣的發現。

studio開發遇到的坑app_name 和apk執行結果的名稱不一樣

今天遇到一個坑: 開發app的時候 設定了application中的label屬性 比如說”啊啊”(@string=app_name) string中設定 app_name=”“啊啊”” 但是真機

Coco2d-x 塔防遊戲“賊來了”開發簡檔

遊戲開發 uml 塔防遊戲 賊來了 原來的教程為《塔防遊戲之賊來了》(這是我之前學習Cocos2d-x時候,看到的一個比較好的教程)原文地址目前只在泰然網看到,http://www.tairan.com/archives/6413 ,原作者為任珊。本文是基於這個教程,而編寫的遊戲開發簡檔,有了這

搭建測試開發環境

adt1. JDK 32位 or 64位 java -version2. ADT 32位 or 64位 下載後,解壓到某個目錄,並配置環境變量:新建ANDROID_HOMED:\adt-bundle-windows-x86_64-20131030\sdkPath,編輯,在後面添加:%AND

Eclipse開發人員的福音

baidu vpn 下載鏈接 .net aid rip track ips .com 我們知道。谷歌已經放棄對Eclipse(ADT)的維護更新了。如今官網上也找不到ADT的下載鏈接了,我們大多數同學仍在使用的ADT版本號可能已經非常老了,預計大多數的S

工程化開發筆記(1)

測試 商業 軟件開發 界面 計算機 數學 開發流程 str sof 2018.3.8日 一、什麽是軟件工程? 1、軟件工程 是把系統的、有序的、可量化的方法應用到軟件的開發、運營和維護上的過程。 2、軟件工程包括下列領域 軟件需求分析、軟件設計、軟件構建、軟件測試和軟件

工程化開發筆記(2)

設計 說明 規劃 選擇 軟件企業 需求分析 結構 系統 周期 一、軟件生命周期 1、軟件定義期: 軟件定義是由軟件系統分析人員和用戶合作,確定軟件是什麽,針對有待開發的軟件系統進行分析、規劃和規格描述,為今後的軟件開發做準備。 (1)軟件任務立項 (2)項目可行性分析 (3