Android TV 开发 (1)
本文来自网易云社区
作者:孙有军
前言
这里主要记录几个TV问题的解决方案,如果对这个不感兴趣的其实就不用往下看了。
这几天有一个需求就是要求出一个TV版本的app,之前没有具体的了解Tv版的app有手机端的app到底有什么区别,因此就做了一下研究,写了些Demo,在做的过程中确实出现了好几个问题。一开始碰到这些问题时,浅尝辄止的试了试,发现很多都没有解决方案,本着外事问google的,search了一把,也没有结果,可能是TV做的人比较少,网上搜出来的都是照着谷歌官方的样例实现了一把而已,因此就仔细的研究了一下这些问题,这里把解决这些问题的方案描述出来,希望其他人能少走弯路,如果有更好的解决方案也希望大家探讨分享。
开发过程
虽然google官方写的是手机app不用做太多改动就可以运行在Tv上,但是终究两种还是有部分区别的,这里还是要针对TV版做部分设置。
首先是配置文件的改动,需要在AndroidManifest中配置如下属性:
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>
<uses-feature
android:name="android.software.leanback"
android:required="true"/>
同时还需要配置一个action为android.intent.action.MAIN,category为android.intent.category.LEANBACK_LAUNCHER的Activity,类似如下:
<activity
android:name="im.yixin.home.HomeActivity"
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>
如果记不住上面需要配置的内容其实也没有关系,可以新创建一个TV工程,默认创建的TV工程就已经包含了上述的配置,并且该工程就相当于一个demo了,是可以直接运行的一个工程,里面包含了Tv开发的很多控件,如果你要学习这也是很好的学习资料了,其实后续的内容也是根据这里的内容进行参照学习的。
这里附带一句,Android的sdk中的samples中的tv样例程序直接导入是运行不起来的,需要修改很多东西,但是实质内容与新创建的工程没有什么区别,因此也可以不用导入样例程序进行学习了。
根据前面的样例图,主界面配置页面如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/global_bg"
android:orientation="vertical"
android:paddingLeft="42dp"
android:paddingRight="42dp"> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/gap_86_dp"
android:clickable="true"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:drawableLeft="@drawable/tv_logo"
android:drawablePadding="@dimen/gap_8_dp"
android:gravity="center"
android:text="@string/itv_name"
android:textColor="@color/white"
android:textSize="@dimen/text_size_20"/> <TextView
android:id="@+id/settings_tab"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/gap_45_dp"
android:background="@drawable/navigation_tab_bar_selector"
android:focusable="true"
android:gravity="center"
android:text="@string/setting"
android:textColor="@color/navigation_text_selector"
android:textSize="@dimen/text_size_20"/> <TextView
android:id="@+id/contact_tab"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/gap_45_dp"
android:layout_toLeftOf="@id/settings_tab"
android:background="@drawable/navigation_tab_bar_selector"
android:focusable="true"
android:gravity="center"
android:text="@string/contact"
android:textColor="@color/navigation_text_selector"
android:textSize="@dimen/text_size_20"/> <TextView
android:id="@+id/dial_tab"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/gap_65_dp"
android:layout_toLeftOf="@id/contact_tab"
android:background="@drawable/navigation_tab_bar_selector"
android:focusable="true"
android:gravity="center"
android:text="@string/dial"
android:textColor="@color/navigation_text_selector"
android:textSize="@dimen/text_size_20"/>
</RelativeLayout> <View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginBottom="@dimen/gap_50_dp"
android:background="@color/gray1"/> <FrameLayout
android:id="@+id/tab_container"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</LinearLayout>
界面的代码如下:
public class HomeActivity extends Activity implements View.OnClickListener { public static void start(Context context) {
Intent intent = new Intent(context, HomeActivity.class);
context.startActivity(intent);
} private static final String[] TAGS = {"dial", "contact", "my"}; private FragmentManager manager; private int showTabIndex = -1; private TextView dialTab;
private TextView contactTab;
private TextView myTab; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
findViews();
setViewsListener();
init();
selectTab(0);
} private void findViews() {
dialTab = (TextView) findViewById(R.id.dial_tab);
contactTab = (TextView) findViewById(R.id.contact_tab);
myTab = (TextView) findViewById(R.id.settings_tab);
} private void setViewsListener() {
dialTab.setOnClickListener(this);
contactTab.setOnClickListener(this);
myTab.setOnClickListener(this);
} private void init() {
manager = getFragmentManager();
} private void selectTab(int index) {
if (index == showTabIndex) {
return;
}
dialTab.setSelected(index == 0);
contactTab.setSelected(index == 1);
myTab.setSelected(index == 2);
FragmentTransaction transaction = manager.beginTransaction();
hideFragment(showTabIndex, transaction);
showTabIndex = index;
showFragment(showTabIndex, transaction);
transaction.commit();
} private void hideFragment(int tabIndex, FragmentTransaction transaction) {
Fragment fragment = getFragmentByIndex(tabIndex);
if (fragment != null) {
transaction.hide(fragment);
}
} private Fragment getFragmentByIndex(int index) {
if (index >= 0 && index < TAGS.length) {
return manager.findFragmentByTag(TAGS[index]);
}
return null;
} private void showFragment(int tabIndex, FragmentTransaction transaction) {
Fragment fragment = getFragmentByIndex(tabIndex);
if (fragment == null) {
switch (tabIndex) {
case 0:
fragment = new DialFragment();
break;
case 1:
/* fragment = new ContactFragment();*/
fragment = new VerticalGridFragment();
break;
case 2:
fragment = new MyFragment();
break;
}
transaction.add(R.id.tab_container, fragment, TAGS[tabIndex]);
//transaction.addToBackStack(TAGS[tabIndex]);
} else {
transaction.show(fragment);
}
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.dial_tab:
selectTab(0);
return;
case R.id.contact_tab:
selectTab(1);
return;
case R.id.settings_tab:
selectTab(2);
// VerticalGridActivity.start(this);
return;
}
} }
该界面主要采用Fragment来实现三个界面,分别为拨号页面,好友,设置界面,其中拨号界面又包含两个子的Fragment,我们来继续看看拨号界面与好友界面,设置界面是一个充数的界面啥都没有做。
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区
相关文章:
【推荐】 基于Docker的UI自动化初探
【推荐】 深入解析SQLServer高可用镜像实现原理
【推荐】 Android输入法弹出时覆盖输入框问题
Android TV 开发 (1)的更多相关文章
- Android TV开发总结(六)构建一个TV app的直播节目实例
请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...
- Android TV开发总结(五)TV上屏幕适配总结
前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...
- Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...
- 聊聊真实的 Android TV 开发技术栈
智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了.但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样. 一.序 ...
- Android TV开发总结(七)构建一个TV app中的剧集列表控件
原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...
- Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听
原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...
- Android TV开发总结(四)通过RecycleView构建一个TV app列表页(仿腾讯视频TV版)
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52854131 前言:昨晚看锤子手 ...
- Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)
前言:上篇是介绍构建TV app前要知道的一些事儿,开发Android TV和手机本质上没有太大的区别,屏大,焦点处理,按键处理,是有别于有手机和Pad的实质区别.今天来介绍TV中Metro UI风格 ...
- Android TV开发总结(一)构建一个TV app前要知道的事儿
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...
随机推荐
- Java-Maven-Runoob:Maven 快照(SNAPSHOT)
ylbtech-Java-Maven-Runoob:Maven 快照(SNAPSHOT) 1.返回顶部 1. Maven 快照(SNAPSHOT) 一个大型的软件应用通常包含多个模块,并且通常的场景是 ...
- python开发面向对象基础:组合&继承
一,组合 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 人类装备了武器类就是组合 1.圆环,将圆类实例后传给圆环类 #!/usr/bin/env python #_*_ ...
- javascript好文分享
JavaScript精华 http://www.cnblogs.com/jesse2013/p/the-part-of-javascript-you-must-know.html JavaScript ...
- catkin 工作空间 - Package 组成
package 是 ROS 软件的基本组织形式,ROS 就是由一个个的 package 组成的 package 是 catkin 的编译基本单元 一个 package 可以包含多个可执行文件(节点) ...
- python---Redis 学习笔记
缓存 前言: 大家都听过缓存,缓存是干啥的呢?我们可以和json和pickle来说,两个程序之间实现信息交互,可以通过在A程序中把数据改成json ,然后传给B程序,通过文件这个介质.文件这个效率很低 ...
- HttpURLConnection连接网页和获取数据的使用实例
HttpURLConnection是java.net 里面自带的一个类,非常好用.虽然现在很多人用阿帕奇的HttpClient,但HttpURLConnection也是个不错的选择. 其实使用方法非常 ...
- C#向pdf 添加水印
调用直接这样用: //PDFHelper.AddImageWatermarkPDF(path, "D://my.pdf", Server.MapPath("/HtmlTo ...
- const与指针的纠缠
当使用带有const的指针时其实有两种意思.一种指的是你不能修改指针本身的内容,另一种指的是你不能修改指针指向的内容. 先说指向const的指针,它的意思是指针指向的内容是不能被修改的.它有两种写法. ...
- laravel Redis缓存
首先在app/config/cache.php配置文件下改变一下缓存的驱动方式改为redis composer require predis/predis 先安装conposer的扩展安装包 然后在c ...
- js,javascript生成 UUID的四种方法
全局唯一标识符(GUID,Globally Unique Identifier)也称作 UUID(Universally Unique IDentifier) . GUID是一种由算法生成的二进制长度 ...