Android TV 开发

行是知之始,知是行之成。这篇文章主要讲述Android TV 开发 相关的知识,希望能为你提供帮助。
【Android TV 开发】
本文来自网易云社区
作者:孙有军


前言

这里主要记录几个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容器的应用场景


    推荐阅读