本文来自网易云社区

作者:孙有军

前言

这里主要记录几个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)的更多相关文章

  1. Android TV开发总结(六)构建一个TV app的直播节目实例

    请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...

  2. Android TV开发总结(五)TV上屏幕适配总结

    前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...

  3. Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...

  4. 聊聊真实的 Android TV 开发技术栈

    智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了.但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样. 一.序 ...

  5. Android TV开发总结(七)构建一个TV app中的剧集列表控件

    原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...

  6. Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听

    原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...

  7. Android TV开发总结(四)通过RecycleView构建一个TV app列表页(仿腾讯视频TV版)

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52854131 前言:昨晚看锤子手 ...

  8. Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)

    前言:上篇是介绍构建TV app前要知道的一些事儿,开发Android TV和手机本质上没有太大的区别,屏大,焦点处理,按键处理,是有别于有手机和Pad的实质区别.今天来介绍TV中Metro UI风格 ...

  9. Android TV开发总结(一)构建一个TV app前要知道的事儿

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...

随机推荐

  1. 完整部署OpenStack-memcache配置

    一.[root@openstack-server ~]# nova listERROR (CommandError): You must provide a username or user id v ...

  2. C#应用调试C++ dll的方法

    最近碰到个C#应用闪退的问题,由于通讯部分调用了C++工程写的dll,下面介绍一种调试的方法. 右键 启动项目,分别配置常规和和调试即可,如下图. 常规中,输出目录设置为安装目录中dll对应的目录: ...

  3. Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够问题)

    Android Studio 安装之后,默认的会给我们创建一个 Nexus 的模拟器, 这个模拟器的镜像文件放在了 C:\Users\Administrator\.android  中 其中的avd文 ...

  4. C#使用 SharpAVI进行 屏幕录制

    再 nuget 中 搜索 shapAvi 并添加引用 github 地址:https://github.com/baSSiLL/SharpAvi using SharpAvi; using Sharp ...

  5. [ShaderStaff] Sprite Outline外轮廓效果

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Unity5.3.8f1 Unity提供了2D Object Sprite对象,但是没有提供外轮廓Outline效果的支持 ...

  6. Python编程总结之常用三方模块

    1.excel读写 利用python进行excel读写是经常遇到的事情,最常用的excel读写模块必属xlrd和xlwt,前者负责读,后者负责写,配合起来可实现读写. 举例1):使用xlrd读取exc ...

  7. Java占位符替换工具类

    import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFact ...

  8. OK6410之tftp下载内核,nfs…

    原文地址:OK6410之tftp下载内核,nfs挂载文件系统全过程详解[转]作者:千山我独行 由于工作的平台也是嵌入式,差不多的平台,所以一直就没有把自己买过来的ok6410板子好好玩玩.以前一直都是 ...

  9. smack 监听不同packet机制

    之前做即时通讯,扒了smack源码来参考.说下其中解包后进行通知的机制. Filter类:accept(Packet packet)函数,传入packet在此函数中进行对比判断,返回true 则通过此 ...

  10. C# XML 操作

    1 xml文件格式 <?xml version="1.0" encoding="utf-8"?> <userInfo> <user ...