• 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输入法弹出时覆盖输入框问题

  • 相关阅读:
    深入理解MySQL开发性能优化.pptx
    公司mysql数据库设计与优化培训ppt
    weblogic 12c下jxls导出excel报错Could not initialize class org.apache.poi.xssf.usermodel.XSSFVMLDrawing
    智软科技医疗器械GSP监管软件通过多省市药监局检查
    论元数据和API管理工具
    sql server 2008空间释放
    论软件系统的设计与开发
    说说IT技术团队招聘那点事
    分布式系统基础设施概览
    分布式环境下rabbitmq发布与订阅端
  • 原文地址:https://www.cnblogs.com/zyfd/p/9705825.html
Copyright © 2020-2023  润新知