第一次開發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"/>
是以大家沒必要太懼怕哈!閑話不說先上效果圖:

這次我使用圖檔的根布局是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疊加的問題,如圖(全是淚):
我們知道出現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最後一個繪制
),此時我換回原本最後繪制的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>
我想做到的就是盡量簡單,一定會有一些地方考慮不周啦!歡迎大家一起讨論呐!