天天看點

androidTV中使用recyclerview并使其item在擷取焦點後擷取邊框,并伴随放大,凸顯效果

第一次開發androidTV端,雖然頁面很簡單,但心中還是難免有些忐忑呢!還好有衆多大神幫助,現已見成效啦!androidTV端與android手機端整體上是一緻的,唯一不同的地方在于TV端存在焦點,視圖的選取需要先将焦點移到這個view上,當界面出現的時候,焦點是預設在電視端的最上方的,當然首先你需要在xml中設定focusable=true,這樣這個view才有擷取焦點的能力:

<ImageView
        android:id="@+id/login"
        android:layout_width="@dimen/width_login_iv"
        android:layout_height="@dimen/height_login_iv"
        android:layout_marginLeft="@dimen/marginLeft_login_iv"
        android:layout_marginTop="@dimen/marginTop_login_iv"
        android:background="@drawable/login_selector"
        android:focusable="true"
        android:onClick="logIn1"/>
           

是以大家沒必要太懼怕哈!閑話不說先上效果圖:

androidTV中使用recyclerview并使其item在擷取焦點後擷取邊框,并伴随放大,凸顯效果
androidTV中使用recyclerview并使其item在擷取焦點後擷取邊框,并伴随放大,凸顯效果

這次我使用圖檔的根布局是recyclerview,item的根布局是cardview,究其原因主要是我在開發前期不知從哪聽來的電視端recyclerview和cardview是标配,其實用什麼都好啦,畢竟時間有限,速速碼字哈!

險些跑題,我是來将擷取焦點突出,放大,加item邊框的好麼!

首先一定要在recyclerview中設定focusable=true!這樣你裡面的item才有能力擷取焦點,下面問題來了,當擷取焦點時,效果怎麼出來呢?首先講一下放大效果:

在android5.0以後才出現的Z軸的概念,是以我直接一步到位,在recyclerview的adapter中onBindViewHolder下:

holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
       //擷取焦點時變化
        if (hasFocus) {
            if(Build.VERSION.SDK_INT>=21){
                ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).translationZ(1).start();
	
	}
           

這樣就可以完美的解決item疊加的問題( 我說的是改變z軸)

都怪google出z軸出的太晚了,現在電視端使用的盒子大多都在5.0以下,我在使用5.0以下版本的盒子的時候出現了item疊加的問題,如圖(全是淚):

androidTV中使用recyclerview并使其item在擷取焦點後擷取邊框,并伴随放大,凸顯效果

我們知道出現item疊加的願意是因為系統繪制也是一個一個繪制的先畫的左上一,其他在他後面畫的,是以當先畫的出現放大效果的時候,如果在5.0之前沒有z軸的概念且選中item附近有在其之後繪制的情況下,那麼該放大item就會在其他item下面展現放大效果,着實蛋疼。說完就打臉,又想到了在網上得到廣泛使用的view.bringToFront();試了一下,未果,原因不詳。苦苦思尋好久,沒辦法了,隻好改變其繪制順序了,問題得以解決:

首先在是主界面綁定

rvMain.setChildDrawingOrderCallback(adapter);
rvMain.setAdapter(adapter);
           

随後在主界面實作:

public class MainRecyclerViewAdapter extends RecyclerView.Adapter<MainRecyclerViewAdapter.Holder> implements RecyclerView.ChildDrawingOrderCallback {
           

随後系統會讓你重寫一個方法:

@Override
    public int onGetChildDrawingOrder(int childCount, int i) {
        focusedChild = mainInterface.rvMain.getFocusedChild();
        focusViewIndex = mainInterface.rvMain.indexOfChild(focusedChild);
        if (focusViewIndex == -1) {
            return i;
        }
        if (focusViewIndex == i) {
            focusid = i;
            return childCount - 1;
        } else if (i == childCount - 1) {
            return focusid;
        } else {
            return i;
        }

    }
           

childCount是可見的item數量,i是你要繪制item的序号,裡面的邏輯是調換可見childCount裡最後繪制的item和焦點選中item的繪制順序。例如裡面有10個item可見的話,childCount是10,i會走10遍(0-9);我寫的focusViewIndex就是焦點選中的序号,如果焦點選中第3個,focusViewIndex=2,當i=2傳入的時候(我要讓這個item最後一個繪制

androidTV中使用recyclerview并使其item在擷取焦點後擷取邊框,并伴随放大,凸顯效果

),此時我換回原本最後繪制的item;而當我傳入原本最後繪制item需要的i時,我要傳回我焦點所在的item的i。

最後在item獲焦事件裡寫道:

//擷取焦點時變化
                    if (hasFocus) {
                        if(Build.VERSION.SDK_INT>=21){
                            ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).translationZ(1).start();
                        }else {
                            ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).start();
                            ViewGroup parent = (ViewGroup) v.getParent();
                            parent.requestLayout();
                            parent.invalidate();

                        }
           

好了,我所了解的item擷取焦點後放大的效果就是這個樣子啦,另外那個背景框的問題呢就是我在item根布局裡寫了一個background,如圖:

android:background="@drawable/item_bg_focus"
           
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:drawable="@drawable/item_boder"/>
</selector>
           
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <corners android:radius="5dp"/>
    <stroke android:color="@color/coloritembackgroud" android:width="5dp" />
</shape>
           

我想做到的就是盡量簡單,一定會有一些地方考慮不周啦!歡迎大家一起讨論呐!

繼續閱讀