Android TV 開發(5)

本文來自網易雲社區android

做者:孫有軍app


問題3:TV launcher中沒有入口圖標ide

若是須要出現入口圖標,你必需要在AndroidManifest中配置action爲android.intent.action.MAIN,category爲android.intent.category.LAUNCHER的Activity。該配置與上面的LEANBACK_LAUNCHER不衝突,能夠對入口Activity配置LAUNCHER,以後一個頁面配置LEANBACK_LAUNCHER,配置以下:
佈局

<activity
    android:name=".WelcomeActivity"
    android:label="@string/app_name"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
    </intent-filter></activity>


問題4:TV launcher中的圖標不清晰,太糊this

若是直接將手機app的launcher圖標直接使用到TV中,則圖標會拉伸,因爲TV的圖標每每都比較大,拉伸後就會變糊,所以須要從新切launcher圖標,手機裏面是4848, 7272,9696等,而tv須要更大的尺寸,雖然沒有在官方找到建議的尺寸,可是這裏推薦一個尺寸180180,能夠多個文件夾都放同一個圖標,這樣界面加載的圖標就會變得清晰。spa



問題5:遙控器導航下一個不是本身但願導航的控件orm

系統中若是界面中有多個可focus的控件,上下左右導航,則會找到與當前控件最鄰近的控件做爲下一個選中的控件,所以若是你確切想指定下一個導航的控件,則能夠指定下一個控件的ID,只要該id在當前顯示的界面中,好比向上 view1.setNextFocusUpId(R.id.dial_tab);xml


問題6:官方VerticalGridFragment加載後,默認選中第一個,可是第一個佔據了整個界面。blog

該問題應該是官方的一個bug,若是不是第一次加載VerticalGridFragment,則不會出現該問題,而且我嘗試了多個版本的,都會出現該問題,緣由是選中後系統會在在選中的控件後插入兩幀NonOverlappingView,插入的佈局代碼以下:繼承


<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v17.leanback.widget.NonOverlappingView      
      android:id="@+id/lb_shadow_normal"       
       android:layout_width="match_parent"      
         android:layout_height="match_parent"      
           android:background="@drawable/lb_card_shadow_normal" />
    <android.support.v17.leanback.widget.NonOverlappingView      
      android:id="@+id/lb_shadow_focused"      
        android:layout_width="match_parent"        
        android:layout_height="match_parent"        
        android:background="@drawable/lb_card_shadow_focused"     
           android:alpha="0" />

</merge>

該佈局插入了兩幀NonOverlappingView,每一幀都使用了一個.9圖標做爲背景,而當系統第一次加載時,最終第一個選中的控件寬高計算錯誤,計算成了一個16777211相似的一個值,遠遠超出了界面的大小,解決方案以下:

方案1,將佈局中的match_parent改成wrap_content 方案2,對VerticalGridFragment中使用的VerticalGridPresenter設置ShadowEnabled,如gridPresenter.setShadowEnabled(false); 方案3,替換掉.9圖片


問題7:VerticalGridFragment加載後,選中放大效果不居中

在VerticalGridFragment,若是ArrayObjectAdapter使用的是本身實現的Presenter,而Presenter使用的不是系統提供的ImageCardView,則會致使選中效果不居中,當選中效果放大後會向右向下覆蓋,而不是在當前位置放大覆蓋四周。

該問題,我查了對應的style、只有針對ImageCardView的style,我也尚未仔細研究怎麼調整,不過這裏給出一個避免的方案,對VerticalGridPresenter選中後的高亮效果選擇爲不放大,如new VerticalGridPresenter(FocusHighlight.ZOOM_FACTOR_NONE)。


問題8:VerticalGridFragment頂層控件不能向上導航

好比在聯繫人列表頁第一行時,遙控器向上不能導航,好比不能導航到撥號,好友控件,該問題實際上是被系統給攔截了。系統的VerticalGridFragment加載了lb_vertical_grid_fragment佈局,該佈局包含了一個BrowseFrameLayout,對 BrowseFrameLayout設置了setOnFocusSearchListener。以下:

   private void setupFocusSearchListener() {
        BrowseFrameLayout browseFrameLayout = (BrowseFrameLayout) getView().findViewById(
                R.id.grid_frame);
        browseFrameLayout.setOnFocusSearchListener(getTitleHelper().getOnFocusSearchListener());
    }

當系統在VerticalGridPresenter最頂層時,向上找最近一個控件時,發現當前佈局已經沒有控件,則會向父佈局查找,代碼以下:

public View focusSearch(View focused, int direction) {   
 if (isRootNamespace()) {        
 // root namespace means we should consider ourselves the top of the
        // tree for focus searching; otherwise we could be focus searching
        // into other tabs.  see LocalActivityManager and TabHost for more info
        return FocusFinder.getInstance().findNextFocus(this, focused, direction);
    } else if (mParent != null) {       
     return mParent.focusSearch(focused, direction);
    }    return null;
}

而VerticalGridPresenter的父佈局則是BrowseFrameLayout,所以最終執行的是上面設置的getTitleHelper().getOnFocusSearchListener(),咱們去看看改listener:

private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =      
      new BrowseFrameLayout.OnFocusSearchListener() {   
           @Override
        public View onFocusSearch(View focused, int direction) {      
              if (focused != mTitleView && direction == View.FOCUS_UP) {        
                      return mTitleView;
            }           
             final boolean isRtl = ViewCompat.getLayoutDirection(focused) ==
                    View.LAYOUT_DIRECTION_RTL;          
                      final int forward = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT;       
                           if (mTitleView.hasFocus() && direction == View.FOCUS_DOWN || direction == forward) {   
                                        return mSceneRoot;
            }        
                return null;
        }
};

發現問題所在沒有,當focused != mTitleView && direction == View.FOCUS_UP時,強制指定了mTitleView,就算沒有沒有顯示title,效果也同樣。我認爲這應該算系統的一個bug,那怎麼解決吶?

咱們能夠重寫一個如出一轍的lb_vertical_grid_fragment,本身寫的佈局會覆蓋掉系統的佈局,再將BrowseFrameLayout重寫成咱們本身的BrowseFrameLayout。以下

public class BrowseFrameLayout extends android.support.v17.leanback.widget.BrowseFrameLayout {    public BrowseFrameLayout(Context context) {        super(context);
    }    public BrowseFrameLayout(Context context, AttributeSet attrs) {        super(context, attrs);
    }    public BrowseFrameLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);
    }    /**
     * Sets a {@link OnFocusSearchListener}.
     */
    public void setOnFocusSearchListener(OnFocusSearchListener listener) {

    }
}


問題9:VerticalGridFragment內容未佔滿整個屏幕

 <!--BrowseFragment, RowsFragment, DetailsFragment padding 左邊的距離</item>-->
<item name="browsePaddingStart">@dimen/lb_browse_padding_start</item>
<!--BrowseFragment, RowsFragment, DetailsFragment padding 右邊的距離</item>-->
<item name="browsePaddingEnd">@dimen/lb_browse_padding_end</item>
<!--BrowseFragment padding 頂部的距離</item>-->
<item name="browsePaddingTop">@dimen/lb_browse_padding_top</item>
<!--BrowseFragment padding 底部的距離</item>-->
<item name="browsePaddingBottom">@dimen/lb_browse_padding_bottom</item>
<!--start margin of RowsFragment inside BrowseFragment when HeadersFragment is visible</item>-->
<item name="browseRowsMarginStart">@dimen/lb_browse_rows_margin_start</item>
<!--top margin of RowsFragment inside BrowseFragment when BrowseFragment title is visible</item>-->
<item name="browseRowsMarginTop">@dimen/lb_browse_rows_margin_top</item>

若是你使用的是BrowseFragment,則控制上述的邊距,若是你使用的是VerticalGridFragment, 則複寫itemsVerticalGridStyle,他也使用了上述定義的值,也能夠直接設置具體的值:

<style name="ItemsVerticalGridStyle" parent="@style/Widget.Leanback.GridItems.VerticalGridView">
    <item name="horizontalMargin">@dimen/gap_12_dp</item>
    <item name="verticalMargin">@dimen/gap_12_dp</item>

    <item name="android:focusable">true</item>
    <item name="android:focusableInTouchMode">true</item>
    <item name="android:paddingStart">?attr/browsePaddingStart</item>
    <item name="android:paddingEnd">?attr/browsePaddingEnd</item>
    <item name="android:paddingBottom">@dimen/lb_vertical_grid_padding_bottom</item>
    <item name="android:paddingTop">?attr/browseRowsMarginTop</item>
    <item name="android:gravity">center_horizontal</item>
    <item name="focusOutFront">true</item>
</style>

樣式調整

若是你須要對VerticalGridFragment的某些樣式進行調整,你能夠從新定義一個Theme繼承自Theme.Leanback,這裏咱們大體寫其中幾個效果。能夠控制VerticalGridFragment的內容的四周的邊距,也能夠控制ImageCardView的視覺效果。

<style name="AppTheme" parent="@style/Theme.Leanback">

    <!--BrowseFragment, RowsFragment, DetailsFragment padding 左邊的距離</item>-->
    <item name="browsePaddingStart">@dimen/lb_browse_padding_start</item>
    <!--BrowseFragment, RowsFragment, DetailsFragment padding 右邊的距離</item>-->
    <item name="browsePaddingEnd">@dimen/lb_browse_padding_end</item>
    <!--BrowseFragment padding 頂部的距離</item>-->
    <item name="browsePaddingTop">@dimen/lb_browse_padding_top</item>
    <!--BrowseFragment padding 底部的距離</item>-->
    <item name="browsePaddingBottom">@dimen/lb_browse_padding_bottom</item>
    <!--start margin of RowsFragment inside BrowseFragment when HeadersFragment is visible</item>-->
    <item name="browseRowsMarginStart">@dimen/lb_browse_rows_margin_start</item>
    <!--top margin of RowsFragment inside BrowseFragment when BrowseFragment title is visible</item>-->
    <item name="browseRowsMarginTop">@dimen/lb_browse_rows_margin_top</item>
    <!--fading edge length of start of browse row when HeadersFragment is visible</item>-->
    <item name="browseRowsFadingEdgeLength">@dimen/lb_browse_rows_fading_edge</item>

    <item name="baseCardViewStyle">@style/BaseCardViewStyle</item>

    <item name="overlayDimMaskColor">@color/transparent</item>
    <item name="overlayDimActiveLevel">@fraction/lb_view_active_level</item>
    <!--控制每個item 背景投影</item>-->
    <item name="overlayDimDimmedLevel">0%</item>

    <item name="itemsVerticalGridStyle">@style/ItemsVerticalGridStyle</item>
</style>

<style name="BaseCardViewStyle" parent="@style/Widget.Leanback.BaseCardViewStyle">
    <item name="cardForeground">@color/transparent</item>
    <item name="cardBackground">@color/transparent</item>
</style>

<style name="ItemsVerticalGridStyle" parent="@style/Widget.Leanback.GridItems.VerticalGridView">
    <item name="horizontalMargin">@dimen/gap_12_dp</item>
    <item name="verticalMargin">@dimen/gap_12_dp</item>

    <item name="android:focusable">true</item>
    <item name="android:focusableInTouchMode">true</item>
    <item name="android:paddingStart">?attr/browsePaddingStart</item>
    <item name="android:paddingEnd">?attr/browsePaddingEnd</item>
    <item name="android:paddingBottom">@dimen/lb_vertical_grid_padding_bottom</item>
    <item name="android:paddingTop">?attr/browseRowsMarginTop</item>
    <item name="android:gravity">center_horizontal</item>
    <item name="focusOutFront">true</item>
</style>

<style name="ImageCardViewInfoAreaStyle" parent="@style/Widget.Leanback.ImageCardView.InfoAreaStyle">
    <item name="android:background">@null</item>
</style>

<style name="ImageCardViewStyle" parent="@style/Widget.Leanback.ImageCardViewStyle">
    <item name="cardBackground">@color/transparent</item>
</style>


網易雲免費體驗館,0成本體驗20+款雲產品! 


更多網易研發、產品、運營經驗分享請訪問網易雲社區


相關文章:
【推薦】 GitLab 自動觸發 Jenkins 構建(2)

相關文章
相關標籤/搜索