本文来自网易云社区

作者:孙有军

前言

这里主要记录几个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. win10 Edge 无法上网代理服务器错误

    当连接好网络时 Edge无法上网,提示代理服务器错误,系统其他非第三方软件同样网络异常 解决:为当前所连接的网络更新自动检测 控制面板->网络和Internet->Internet选项-& ...

  2. linux composer的使用

    安装好的composer使用很简单,分两步加载组件例1.搜索组件:composer search phpexcel2.下载组件:composer require 厂商名/包名然后在使用该插件的脚本中引 ...

  3. keil的使用:新建Project

    新建项目--->新建文件夹----->把新建的项目放在自己的文件夹中------>选择开发板------>添加开发板的驱动文件---->main函数 项目分组基本如图,S ...

  4. mysql之数据类型以及操作数据表

    数据类型: 数据类型是指列.存储过程的参数.表达式和局部变量的数据特征,它决定了数据的存储格式,代表了不同的信息类型. ———————————————————————————————————————— ...

  5. android 命名规则

    包名结构: 资源命名方式:

  6. C99标准新特性的说明

    C99标准新特性的说明   一.说明 ====== 这里的讨论的是C语言的国际标准,即国际标准化组织ISO,制定的C语言标准.历史上ISO制定过4个版本的C语言标准,他们分别是:C90(ISO/IEC ...

  7. Mediator模式

    [Mediator模式] 通过mediator来让各个相互通知的对象解耦.在iOS框架中就是NSNotificationCenter. 参考:http://www.jdon.com/designpat ...

  8. 回车换行0x0D和0x0A 小谈

    在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符.但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符.要是在这 ...

  9. Android selector中的item的顺序

    在selector中,要将默认状态的item放在最后面,因为一旦前面的item满足匹配条件,后面的item就不会去匹配.因此,把默认状态的item放在前面的话,后面的item没有执行的机会

  10. sudo apt install libreadline-dev Reading package lists... Error!

    luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ ...