本人由于最近一段时间很忙,一直都没有更新 android tv的开源库了,因为技术的更新迭代,TV开发的库已经升级为Leanback + 移动边框等等东西,希望这篇文章能激发你对于 Android TV 更多的想法,水平有限,互相学习,谢谢.
Android tv 开源社区地址:https://gitee.com/kumei (欢迎加入)
Android tv 开源社区收集的库:https://gitee.com/kumei/Android_tv_libs
Leanback demo地址: https://github.com/googlesamples/leanback-showcase
谷歌官方的 demo 中 是这样的,那样的... ...,都是围绕 Fragment展开的.
如果真不想用谷歌自带的Fragment,想单独使用,或者写自己的标题栏或者多级菜单,这么办?
先来一张图片,类似下图的布局确实很酷炫.
如何使用 Leanback 的库
- 直接Adnroid studio 导入,版本有差异化,不懂的百度查,github看.
- github.com/FrozenFreeF… 这里我直接使用 从v14导出来的Leanback.
使用Leanback弄出下面的界面
我感觉不用分析什么Leabnack,也不用讲解一大堆如何使用,我下面就直接贴代码,并注释吧.
先来分析下上图,标题栏 + ViewPager(包含多个Fragment)
如果标题栏使用 Recyclerview 或者横向的布局,你都要处理焦点记忆问题,
这里推荐使用 Leanback 的 HorizontalGridView 作为标题栏使用,已经帮你处理焦点记忆问题,并且很不错.
标题栏
xml 大概如下 布局如下
<!-- 影视标题栏 -->
<com.open.leanback.widget.HorizontalGridView
android:id="@+id/****"
android:layout_width="match_parent"
android:layout_height="@dimen/title_h" />
<!-- 影视内容 -->
<android.support.v4.view.ViewPager
android:id="@+id/*****"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
HorizontalGridView 其实继承的 RecyclerView,使用方式是一样的.
mTitlerAdapter = new TitlerAdapter();
titleHgridview.setAdapter(mTitlerAdapter);
// 进行强转,GridLayoutManager.
((GridLayoutManager)titleHgridview.getLayoutManager()).setOnChildSelectedListener(new OnChildSelectedListener() {
@Override
public void onChildSelected(ViewGroup parent, View view, int position, long id) {
// 选中某个item的处理, 比如翻页等等操作
}
});
这里给大家介绍一个小技巧 android:duplicateParentState="" 的使用,再配合 selector,然后布局里面的 控件都可以获取到父布局的属性,爽歪歪.
ViewPager内容
- 布局里面使用 VerticalGridView,这里就相当使用 GridView,类似下图.
mMoviceAdapter = new MoviceAdapter();
moviceVgridview.setAdapter(mMoviceAdapter);
// 初始化影视垂直布局.
moviceVgridview.setNumColumns(6);
// 因为标题下面布局的焦点上不去标题栏,需要设置,具体原理参考源码.
((GridLayoutManager)moviceVgridview.getLayoutManager()).setFocusOutAllowed(true, true);
((GridLayoutManager)moviceVgridview.getLayoutManager()).setOnChildSelectedListener(new OnChildSelectedListener() {
@Override
public void onChildSelected(ViewGroup parent, View view, int position, long id) {
}
});
// FocusOutAllowed focusOutSidAl... 也可以再xml设置,设置的属性如下,具体参考谷歌demo
<declare-styleable name="lbBaseGridView">
<attr name="focusOutFront" format="boolean"/>
<attr name="focusOutEnd" format="boolean"/>
<attr name="focusOutSideStart" format="boolean"/>
<attr name="focusOutSideEnd" format="boolean"/>
<attr name="horizontalMargin" format="dimension"/>
<attr name="verticalMargin" format="dimension"/>
<attr name="android:gravity"/>
</declare-styleable>
- 如果想实现复杂的带标题栏的布局,类似下面的,或者小米瀑布流的.
// 使用 Leanback下列的数据结构,设置的方式和 Recyclerview差不多,具体也可以参考 Leabanck 的谷歌demo.
ItemBridgeAdapter mItemBridgeAdapter;
mVerticalGridView.setAdapter(mItemBridgeAdapter);
// 测试数据,demo.
public ItemBridgeAdapter getMoviceItemDatas() {
mItemBridgeAdapter = new ItemBridgeAdapter();
CardPresenter cardPresenter = new CardPresenter();
final NewPresenterSelector newPresenterSelector = new NewPresenterSelector();
ArrayObjectAdapter mRowsAdapter = new ArrayObjectAdapter(newPresenterSelector); // 填入Presenter选择器.
for (int i = 0; i < 100; i++) {
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
MoviceItemData moviceItemData = mMoviceItemData.get(i); // 包含标题+内容列表的数据
String title = moviceItemData .getTitle();
HeaderItem settingHeader = new HeaderItem(i, title); // 标题头(比如 xxx榜单)
List<SettingItem> items = moviceItemData.getItems(); // 内容列表.(影视内容)
// 小技巧: 比如需要像图片中的频道一样,这里服务端返回的数据很多,换行了,
// 可以进数据分段,一行8个填入,最后一行的,设置 ListRow(null, listRowAdapter2),那么标题栏就没有了.
//
ArrayObjectAdapter listRowAdapter2 = new ArrayObjectAdapter(cardPresenter);
listRowAdapter2.addAll(0, items);
ListRow listRow2 = new ListRow(settingHeader, listRowAdapter2);
mRowsAdapter.add(listRow2);
}
mItemBridgeAdapter.setAdapter(mRowsAdapter);
return mItemBridgeAdapter;
}
PresenterSelector 选择器,具体可以参考谷歌demo.
public class NewPresenterSelector extends PresenterSelector {
private AListRowPresenter mNewListRowPresenter = new AListRowPresenter();
private ARowPresenter mNewListRowPresenter2 = new AListRowPresenter();
public NewPresenterSelector() {
}
@Override
public Presenter getPresenter(Object item) {
// 根据item判断,加载相应的 presenter,这里主要为了显示不同的东西.
}
@Override
public Presenter[] getPresenters() {
return new Presenter[]{
*** ***
};
}
}
如何添加按键加载更多
由于TV上面属于遥控器操作,不像手机上面那样.
@Override
public void onScrollStateChanged(int state) {
if (state == SCROLL_STATE_IDLE) {
if (getLastVisiblePosition() >= getAdapter().getItemCount() - 1) {
// 加载更多
}
}
super.onScrollStateChanged(state);
}
public int getLastVisiblePosition() {
final int childCount = getChildCount();
if (childCount == 0)
return 0;
else
return getChildAdapterPosition(getChildAt(childCount - 1));
}
// 也可以再这里进行处理,具体看需求了,还有个人喜好.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return super.dispatchKeyEvent(event);
}
如何适配不同分辨率
我这里使用的是 AutoLayout,我以前也写过一篇文章 android tv如何适配不同平台,这里就不过多废话了.
放大效果
配合移动边框边框使用
性能优化
有空后续整理到文章,笔记更新处:b53aa9d9.wiz03.com/share/s/2Re…