Android TV 開發(5)
本文來自網易雲社群
作者:孫有軍
問題3:TV launcher中沒有入口圖示
如果需要出現入口圖示,你必須要在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中的圖示不清晰,太糊
如果直接將手機app的launcher圖示直接使用到TV中,則圖示會拉伸,由於TV的圖示往往都比較大,拉伸後就會變糊,因此需要重新切launcher圖示,手機裡面是4848, 7272,9696等,而tv需要更大的尺寸,雖然沒有在官方找到建議的尺寸,但是這裡推薦一個尺寸180180,可以多個資料夾都放同一個圖示,這樣介面載入的圖示就會變得清晰。
問題5:遙控器導航下一個不是自己希望導航的控制元件
系統中如果介面中有多個可focus的控制元件,上下左右導航,則會找到與當前控制元件最鄰近的控制元件作為下一個選中的控制元件,因此如果你確切想指定下一個導航的控制元件,則可以指定下一個控制元件的ID,只要該id在當前顯示的介面中,比如向上 view1.setNextFocusUpId(R.id.dial_tab);
問題6:官方VerticalGridFragment載入後,預設選中第一個,但是第一個佔據了整個介面。
該問題應該是官方的一個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>
網易雲ofollow,noindex" target="_blank">免費體驗館 ,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社群