聊一聊 Leanback 中的 HorizontalGridView

云視聽極光截圖.png

??Google 的 Leanback 有其固定的風(fēng)格,但國內(nèi)的UI往往不會按照 Leanback 的風(fēng)格進行設(shè)計筑舅,比如說上面的云視聽極光。這就導(dǎo)致 Android TV 的那些封裝好的 Fragment庄岖、Presenter 等控件我們基本上用不到豁翎,局限性很強,所以隅忿,如果想要既使用 Leanback 的放大效果心剥,又要同時按國內(nèi)的 UI 風(fēng)格做出國內(nèi)界面的樣子的話,只能使用適應(yīng)性較強的控件背桐,比如如 HorizontalGridView优烧、VerticalGridView。那就要求我們要盡可能的熟悉 HorizontalGridView链峭、VerticalGridView 這些控件的使用方式畦娄。
??下面就記錄一下 HorizontalGridView 相關(guān)的東西。
??HorizontalGridView 繼承自抽象類 BaseGridView弊仪,而 BaseGridView 又繼承自 RecyclerView熙卡,也就是說 HorizontalGridView 是 RecyclerView 的子類,對于 HorizontalGridView 來說励饵,RecyclerView 有的特性基本上也適用于 HorizontalGridView驳癌,也可以認(rèn)為 HorizontalGridView 就是針對 TV 再次封裝的 RecyclerView 。
??這次就對照下圖所示的云視聽極光的標(biāo)題欄來寫個 demo 役听,順便梳理一下 HorizontalGridView 的一些屬性和方法颓鲜。

image.png

1 基本使用

1.1 新建項目,添加依賴

??如果想要使用Leanback典予,首先要添加 如下所示的 Leanback 的依賴甜滨。

    implementation 'com.android.support:leanback-v17:28.0.0'

1.2 修改 activity_main.xml

??在 activity_main.xml 中添加標(biāo)題欄的 HorizontalGridView。修改后如下所示瘤袖。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#000000">

    <android.support.v17.leanback.widget.HorizontalGridView
        android:id="@+id/hg_title"
        android:layout_width="wrap_content"
        android:layout_height="50dp" />

</android.support.constraint.ConstraintLayout>

1.3 創(chuàng)建 Presenter

??Presenter 是 HorizontalGridView 用來綁定衣摩、展示子 Item 的類,類比著想的話捂敌,它就是和 RecyclerView 的 Adapter 起著一樣的作用的東西昭娩,它們都有 onCreateViewHolder、onBindViewHolder 這樣的方法黍匾,都有繼承自 ViewHolder 的靜態(tài)內(nèi)部類∏喊穑看看下面 TitlePresenter 這個類就會覺得十分熟悉锐涯。
??那就分析分析吧。
??一樣之處:它們都是在 onCreateViewHolder 里加載 item 的布局填物,在 onBindViewHolder 里綁定數(shù)據(jù)纹腌,在內(nèi)部類 ViewHolder 中接收由布局生成的子 View霎终,并加載子 View 中的控件。
??不一樣之處:不一樣的是 RecyclerView 的 Adapter 有 notifyDataSetChanged升薯、notifyItemChanged莱褒、notifyItemMoved、notifyItemRangeChanged 這樣的數(shù)據(jù)刷新的方法涎劈,而在 HorizontalGridView 中广凸,這些功能都抽出來了,它們都放到了 ObjectAdapter 這個抽象類及其子類中了蛛枚,這是 MVP 設(shè)計模式的寫法谅海,同時我覺得這也體現(xiàn)了單一職責(zé)的思想。
??這里還有一些不關(guān)鍵的類和 xml 沒貼出來蹦浦,有需要去文章末尾百度云下載項目看吧扭吁。

TitlePresenter.class

package isuperred.github.com.horizontalgeidviewdemo;

import android.support.v17.leanback.widget.Presenter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class TitlePresenter extends Presenter {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_title, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object o) {
        if (o instanceof Title) {
            ViewHolder vh = (ViewHolder) viewHolder;
            vh.tvTitle.setText(((Title) o).getName());
        }
    }

    @Override
    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {

    }

    static class ViewHolder extends Presenter.ViewHolder {
        TextView tvTitle;

        public ViewHolder(View view) {
            super(view);
            tvTitle = view.findViewById(R.id.tv_title);
        }
    }
}

1.4 初始化 HorizontalGridView 并為之綁定適配器、數(shù)據(jù)

??先通過 findViewById 獲取 HorizontalGridView 的對象盲镶,通過 setHorizontalSpacing 這個方法在 item 之間添加間距侥袜,ArrayObjectAdapter 用于數(shù)據(jù)的綁定、數(shù)據(jù)的刷新溉贿,ItemBridgeAdapter 也可以進行數(shù)據(jù)刷新枫吧,它是全部刷新一遍,比較重顽照,它更重要的是起一個橋梁的作用由蘑,將 ObjectAdapter、PresenterSelector代兵、Presenter聯(lián)系起來尼酿。
MainActivity.class

package isuperred.github.com.horizontalgeidviewdemo;

import android.os.Bundle;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.FocusHighlight;
import android.support.v17.leanback.widget.FocusHighlightHelper;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.support.v17.leanback.widget.ItemBridgeAdapter;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        HorizontalGridView horizontalGridView = findViewById(R.id.hg_title);
        horizontalGridView.setHorizontalSpacing(30);
        ArrayObjectAdapter arrayObjectAdapter = new ArrayObjectAdapter(new TitlePresenter());
        ItemBridgeAdapter itemBridgeAdapter = new ItemBridgeAdapter(arrayObjectAdapter);
        /*FocusHighlightHelper.setupBrowseItemFocusHighlight(itemBridgeAdapter,
                FocusHighlight.ZOOM_FACTOR_LARGE, true);*/
        horizontalGridView.setAdapter(itemBridgeAdapter);
        arrayObjectAdapter.addAll(0, TitleModel.getTitleList());

    }
}

1.5 效果圖

??代碼寫完效果就是下面這樣了,我這是在電視上運行后的效果植影。

效果圖.png

2 一些屬性裳擎、方法

2.1 focusOutFront、focusOutEnd

image.png

??像上面云視聽極光所示思币,如果標(biāo)題欄使用 HorizontalGridView 實現(xiàn)鹿响,內(nèi)容區(qū)域使用 Fragment 里放的 VerticalGridView 實現(xiàn),可能出現(xiàn)標(biāo)題欄和內(nèi)容區(qū)焦點切換不成功的問題谷饿,比如說惶我,焦點不能從內(nèi)容區(qū)切到標(biāo)題欄這樣的情況。這時使用 focusOutFront 和 focusOutEnd 屬性能夠解決問題博投,解決不同容器里焦點切換不成功的問題绸贡。使用方式如下所示。

<android.support.v17.leanback.widget.HorizontalGridView
        android:id="@+id/hg_title"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        app:focusOutEnd="true"
        app:focusOutFront="true"/>

??這2個屬性在源碼中是通過調(diào)用 GridLayoutManager 的 setFocusOutAllowed 方法來使用的。

image.png

2.2 setHorizontalSpacing

??沒什么說的听怕,就是設(shè)置 HorizontalGridView 的 Item 之間的間距捧挺。setHorizontalMargin 已經(jīng)被棄用了。

image.png

2.3 setFocusScrollStrategy

??setFocusScrollStrategy 用來設(shè)置焦點的滾動方式尿瞭,它的參數(shù)有3個可選值闽烙,分別為 FOCUS_SCROLL_ALIGNEDFOCUS_SCROLL_ITEMFOCUS_SCROLL_PAGE声搁,默認(rèn)值為 FOCUS_SCROLL_ALIGNED黑竞;值得一提的是,HorizontalGridView 和 VerticalGridView 的默認(rèn)焦點搜索規(guī)則是溯源原則酥艳,而設(shè)置焦點滾動方式為 FOCUS_SCROLL_ITEM 后摊溶,焦點搜索規(guī)則變?yōu)榱司徒瓌t。
setFocusScrollStrategy 使用方式如下所示充石。

     horizontalGridView.setFocusScrollStrategy(HorizontalGridView.FOCUS_SCROLL_ITEM);
     verticalGridView.setFocusScrollStrategy(HorizontalGridView.FOCUS_SCROLL_ITEM);

??FOCUS_SCROLL_ALIGNED:焦點在中間

焦點在中間.gif

??FOCUS_SCROLL_ITEM:焦點在末尾

焦點在末尾.gif

??FOCUS_SCROLL_PAGE:翻頁

翻頁.gif

2.4 setNumRows

??setNumRows 用于設(shè)置行數(shù)莫换,默認(rèn) HorizontalGridView 為一行,通過 setNumRows 方法可以設(shè)置多行骤铃。但有個注意點拉岁,設(shè)置多行后要注意 position 的位置。舉個例子惰爬,2 行的 HorizontalGridView喊暖,第一行第一個模塊 position 為 0,而 position 為 1 的模塊是 第二行第一個撕瞧,而非第一行第二個陵叽。如下圖所示。

image.png

2.5 setRowHeight

??注意了丛版,setRowHeight 是用來設(shè)置 HorizontalGridView 的 Item 的高度巩掺,而不是用來設(shè)置 HorizontalGridView 的高度。

2.6 setSelectedPosition页畦、setSelectedPositionSmooth

??setSelectedPosition 和 setSelectedPositionSmooth 都是讓某個 position 獲取焦點胖替,區(qū)別在于 setSelectedPositionSmooth 在移動時更平滑一點。

2.7 duplicateParentState

image.png

??這個屬性還是很有用的豫缨。舉個例子独令,上圖是小米電視的【我的應(yīng)用】頁面,體驗一下能夠感受到:它的放大的焦點 View 是每個 Item 的最外層布局好芭,而不是圖標(biāo)那個View燃箭,但是其焦點框卻套在了圖標(biāo)那個 View 上,那這種效果如果我來實現(xiàn)就會用到 duplicateParentState 屬性了舍败。duplicateParentState 的意思是:當(dāng)前控件是否跟隨父控件的(點擊招狸、焦點等)狀態(tài)碗硬。下面簡單寫一下其使用方式。

image.png

??如上圖所示瓢颅,最外層布局設(shè)置可點擊、可獲取焦點弛说,在 ImageView 里設(shè)置了 duplicateParentState 屬性挽懦,表示跟隨父控件狀態(tài),所以在父控件獲取焦點時木人,ImageView 也可以獲取焦點信柿。ImageView 設(shè)置了一個背景 bg_focus_border,bg_focus_border 是一個Selector醒第,里邊設(shè)置了焦點態(tài)和非焦點態(tài)的邊框渔嚷。這樣,Item 的獲取焦點時稠曼,圖標(biāo)就會顯示有焦點框了形病。

3 代碼

??沒多少代碼,就只傳了標(biāo)題欄的代碼霞幅。
??百度云盤下載代碼鏈接:https://pan.baidu.com/s/14Rf1XZMSxJQCH6dlmd4ICw
??提取碼:gkaj

4 結(jié)語

??還有很多不會的漠吻,不知道的東西,慢慢學(xué)習(xí)吧司恳。路漫漫其修遠兮途乃!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扔傅,隨后出現(xiàn)的幾起案子耍共,更是在濱河造成了極大的恐慌,老刑警劉巖猎塞,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件试读,死亡現(xiàn)場離奇詭異,居然都是意外死亡邢享,警方通過查閱死者的電腦和手機鹏往,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骇塘,“玉大人伊履,你說我怎么就攤上這事】钗ィ” “怎么了唐瀑?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長插爹。 經(jīng)常有香客問我哄辣,道長请梢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任力穗,我火速辦了婚禮毅弧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘当窗。我一直安慰自己够坐,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布崖面。 她就那樣靜靜地躺著元咙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巫员。 梳的紋絲不亂的頭發(fā)上庶香,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音简识,去河邊找鬼赶掖。 笑死,一個胖子當(dāng)著我的面吹牛财异,可吹牛的內(nèi)容都是我干的倘零。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼戳寸,長吁一口氣:“原來是場噩夢啊……” “哼呈驶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疫鹊,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤袖瞻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拆吆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聋迎,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年枣耀,在試婚紗的時候發(fā)現(xiàn)自己被綠了霉晕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡捞奕,死狀恐怖牺堰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情颅围,我是刑警寧澤伟葫,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站院促,受9級特大地震影響筏养,放射性物質(zhì)發(fā)生泄漏斧抱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一渐溶、第九天 我趴在偏房一處隱蔽的房頂上張望辉浦。 院中可真熱鬧,春花似錦茎辐、人聲如沸盏浙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至竹海,卻和暖如春慕蔚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背斋配。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工孔飒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人艰争。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓坏瞄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甩卓。 傳聞我的和親對象是個殘疾皇子鸠匀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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