接下来我们就开始分析一下代码部分,这里我就转载其他人写的吧,我一开始也是参考这篇文章的。
当然,我自己也添加了我自己在开发过程中写的代码和注释,对于新手来说没有这些注释还真的消耗头发
转载地址:https://blog.csdn.net/lzybilian/article/details/80001032
(AndroIDManifest.xml)
<uses-permission androID:name="androID.permission.INTERNET" /> //这是申请网络的权限<uses-permission androID:name="androID.permission.RECORD_AUdio" /> //这是申请开发音频的权限<uses-feature androID:name="androID.harDWare.touchscreen" androID:required="false" /> //因为电视一般不支持触屏,所以需要声明一下权限<uses-feature androID:name="androID.software.leanback" androID:required="true" /> //使用一些TV下面的控件时,需要的声明<activity androID:name=".MainActivity" androID:banner="@drawable/app_icon_your_company" androID:icon="@drawable/app_icon_your_company" androID:label="@string/app_name" androID:logo="@drawable/app_icon_your_company" androID:screenorIEntation="landscape"> <intent-filter> <action androID:name="androID.intent.action.MAIN" /> //因为我做的是桌面,所以加上了这两句 <category androID:name="androID.intent.category.HOME" /> <category androID:name="androID.intent.category.DEFAulT" /> //这个地方与手机端开发区别较大,这个主要是声明了这是一个TV项目,如果不加这个,那么运行在TV上时,是找不到这个应用的运行图标的 //但是我依然找不到图标哈哈,以后发现了问题所在再写下来吧 <category androID:name="androID.intent.category.LEANBACK_LAUNCHER" /> </intent-filter></activity>
然后我就打开了MainActivity.xml,然后我发现里面竟然是空的。随后我就打开了MainActivity的资源文件。
<fragment xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:ID="@+ID/main_browse_fragment" androID:name="com.example.administrator.myfirst.MainFragment" //这里是关键点,原来里面是引用了一个碎片。 androID:layout_wIDth="match_parent" androID:layout_height="match_parent" tools:context="com.example.administrator.myfirst.MainActivity" tools:deviceids="tv" tools:ignore="MergeRootFrame" />
然后就可以打开MainFragment.java。里面有四个方法,我们一一来分析一下。
//这些也写出来吧,不然看起来耗头发 private static final String TAG = "MainFragment"; private static final int BACKGROUND_UPDATE_DELAY = 300; private static final int GRID_ITEM_WIDTH = 200; private static final int GRID_ITEM_HEIGHT = 200; private final Handler mHandler = new Handler(); private Drawable mDefaultBackground; private displayMetrics mMetrics; private Timer mBackgroundTimer; private String mBackgroundUri; private BackgroundManager mBackgroundManager; private List<ResolveInfo> apps_List = MainActivity.apps; private List<String> sys_apps_name = MainActivity.system_app_name; private List<String> my_apps_name = MainActivity.my_app_name; private List<String> apps_name = MainActivity.name; private List<String> apps_pak = MainActivity.pak; private List<String> apps_cla = MainActivity.cla;
public voID onActivityCreated(Bundle savedInstanceState) { Log.i(TAG, "onCreate"); super.onActivityCreated(savedInstanceState); prepareBackgroundManager(); setupUIElements(); loadRows(); setupEventListeners();}
这里大家一看就明白这个方法的作用,初始化。
private voID prepareBackgroundManager() { mBackgroundManager = BackgroundManager.getInstance(getActivity()); mBackgroundManager.attach(getActivity().getwindow()); //设置右边应用区域的背景颜色,被这个东西坑惨了ContextCompat.getcolor(),看了下面的代码才反应过来 //其实我也不知道它的原理是什么,参考百度吧 mBackgroundManager.setcolor(ContextCompat.getcolor(getActivity(), R.color.search_opaque)); mDefaultBackground = getResources().getDrawable(R.drawable.default_background); mMetrics = new displayMetrics(); getActivity().getwindowManager().getDefaultdisplay().getMetrics(mMetrics);}private voID setupUIElements() { // setBadgeDrawable(getActivity().getResources().getDrawable( // R.drawable.vIDeos_by_Google_banner)); setTitle(getString(R.string.browse_Title)); // Badge, when set, takes precedent // over Title setheadersstate(headerS_ENABLED); setheadersTransitionOnBackEnabled(false); //这里是设置左边引导的显示与否。 // set fastLane (or headers) background color setBrandcolor(getResources().getcolor(R.color.background_gradIEnt_start)); //设置左边引导的背景色 // set search icon color setSearchAffordancecolor(getResources().getcolor(R.color.search_opaque));}
这个方法主要作用是产生页面数据
private voID loadRows() { List<MovIE> List = MovIEList.setupMovIEs(); //MovIE一个实现了序列化的Bean。setupMovIEs()是产生movIE数据的方法 mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); //页面数据的适配器 CardPresenter cardPresenter = new CardPresenter(); //这个比较重要下面贴上源码 int sys_app_layer = 0; int my_app_layer = 0; if((sys_apps_name.size() % 8) == 0) { sys_app_layer = (sys_apps_name.size() / 8); } else { sys_app_layer = (sys_apps_name.size() / 8) +1; } //(字怎么变黄了???) if((my_apps_name.size() % 8) == 0) { my_app_layer = (sys_apps_name.size() / 8); } else { my_app_layer = (sys_apps_name.size() / 8) +1; } //应领导要求,将app分成系统应用和第三方应用 int i; headerItem header1 = new headerItem(0, MovIEList.MOVIE_category[0]); for (i = 0; i < sys_app_layer; i++) { ArrayObjectAdapter ListRowAdapter = new ArrayObjectAdapter(cardPresenter); for (int j = 0; j < 8 && ((8*i + j) < sys_apps_name.size()); j++) { //Log.d(TAG,"List.get["+(8*i+j)+"]:"+List.get(8*i + j)); ListRowAdapter.add(List.get(8*i + j)); } if(i == 0) { rowsAdapter.add(new ListRow(header1, ListRowAdapter)); } else { rowsAdapter.add(new ListRow(ListRowAdapter)); } } headerItem header2 = new headerItem(i, MovIEList.MOVIE_category[1]); for (i = 0; i < my_app_layer; i++) { ArrayObjectAdapter ListRowAdapter = new ArrayObjectAdapter(cardPresenter); for (int j = 0; j < 8 && ((8*i + j) < my_apps_name.size()); j++) { //Log.d(TAG,"List.get["+(8*i+j)+"]:"+List.get(8*i + j)); ListRowAdapter.add(List.get(8*i + j + sys_apps_name.size())); } if(i == 0) { rowsAdapter.add(new ListRow(header2, ListRowAdapter)); } else { rowsAdapter.add(new ListRow(ListRowAdapter)); } } headerItem grIDheader = new headerItem(i, "PREFERENCES"); GrIDItemPresenter mGrIDPresenter = new GrIDItemPresenter(); ArrayObjectAdapter grIDRowAdapter = new ArrayObjectAdapter(mGrIDPresenter); //里面传了一个Presenter grIDRowAdapter.add(getResources().getString(R.string.grID_vIEw)); grIDRowAdapter.add(getString(R.string.error_fragment)); grIDRowAdapter.add(getResources().getString(R.string.personal_settings)); mRowsAdapter.add(new ListRow(grIDheader, grIDRowAdapter)); //看了这个应该很清晰了 setAdapter(mRowsAdapter); //最后将mRowsAdapter设置}
主要就是实现了每个控件的绑定,设置数据
public class CardPresenter extends Presenter { private static final String TAG = "CardPresenter"; private static final int CARD_WIDTH = 313; private static final int CARD_HEIGHT = 176; private static int sSelectedBackgroundcolor; private static int sDefaultBackgroundcolor; private Drawable mDefaultCardImage; private static voID updateCardBackgroundcolor(ImageCardVIEw vIEw, boolean selected) { int color = selected ? sSelectedBackgroundcolor : sDefaultBackgroundcolor; // Both background colors should be set because the vIEw's background is temporarily visible // during animations. vIEw.setBackgroundcolor(color); vIEw.findVIEwByID(R.ID.info_fIEld).setBackgroundcolor(color); } @OverrIDe public VIEwHolder onCreateVIEwHolder(VIEwGroup parent) { Log.d(TAG, "onCreateVIEwHolder"); sDefaultBackgroundcolor = parent.getResources().getcolor(R.color.default_background); sSelectedBackgroundcolor = parent.getResources().getcolor(R.color.selected_background); /* * This template uses a default image in res/drawable, but the general case for AndroID TV * will require your resources in xhdpi. For more information, see * https://developer.androID.com/training/tv/start/layouts.HTML#density-resources */ //下面这个mDefaultCardImage我将它移到了onBindVIEwHolder方法里面 //mDefaultCardImage = parent.getResources().getDrawable(R.drawable.movIE); ImageCardVIEw cardVIEw = new ImageCardVIEw(parent.getContext()) { @OverrIDe public voID setSelected(boolean selected) { updateCardBackgroundcolor(this, selected); //这句很关键,它实现了当选择改变的时候,选中效果的出现 super.setSelected(selected); } }; cardVIEw.setFocusable(true); cardVIEw.setFocusableIntouchMode(true); updateCardBackgroundcolor(cardVIEw, false); return new VIEwHolder(cardVIEw); } @OverrIDe public voID onBindVIEwHolder(Presenter.VIEwHolder vIEwHolder, Object item) { MovIE movIE = (MovIE) item; //这里是根据item的Title与列表apps_name做对比,目的是获得i,获得准确的apps_icon //至于为什么这样做,我会在文章后面画个图解释 for(int i=0; i<apps_name.size(); i++) { if(((MovIE) item).getTitle() == apps_name.get(i)) { mDefaultCardImage = apps_icon.get(i); } } ImageCardVIEw cardVIEw = (ImageCardVIEw) vIEwHolder.vIEw; Log.d(TAG, "onBindVIEwHolder"); if (movIE.getCardImageUrl() != null) { cardVIEw.setTitleText(movIE.getTitle()); //cardVIEw.setContentText(movIE.getStudio()); //这里是设置layout与父组件边框的距离,我没有找到调节父组件之间的距离的方法 //领导又觉得它们挤着慌,只好改一下这里了 FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); layout.setmargins(30, 15, 30, 15); //设置图标与父控件的距离,这里可以调节图标大小和形状 //说到这不得不承认我真的是菜,我没有找到将图标设置成原图的方法,只能这样把它硬挤成型 ImageVIEw imageVIEw = cardVIEw.getMainImageVIEw(); imageVIEw.setpadding(75, 25, 75, 25); imageVIEw.setScaleType(ImageVIEw.ScaleType.FIT_XY); cardVIEw.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT); GlIDe.with(vIEwHolder.vIEw.getContext()) .load(movIE.getCardImageUrl()) .centerCrop() .error(mDefaultCardImage) .into(layout); } } @OverrIDe public voID onUnbindVIEwHolder(Presenter.VIEwHolder vIEwHolder) { Log.d(TAG, "onUnbindVIEwHolder"); ImageCardVIEw cardVIEw = (ImageCardVIEw) vIEwHolder.vIEw; // Remove references to images so that the garbage collector can free up memory cardVIEw.setBadgeImage(null); cardVIEw.setMainImage(null); }}
这个方法设置了监听
private voID setupEventListeners() { setonSearchClickedListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw vIEw) { //左上角搜索点击事件 Toast.makeText(getActivity(), "Implement your own in-app search", Toast.LENGTH_LONG) .show(); } }); //item的监听 setonItemVIEwClickedListener(new ItemVIEwClickedListener()); setonItemVIEwSelectedListener(new ItemVIEwSelectedListener());}
解释一下之前的那个循环吧,下面图中的大黑框是屏幕,黑框外面的小框则是超出屏幕外面的图标,图标下面都有app的名字我这里是把app的各种信息分别存在不同的列表中,位置也是对应好的;但是一打开应用我就傻眼了,app名字和图标对应不上,原因就在于它加载图标时先把屏幕内的填上,再搞屏幕外面的。所以我就只能根据app名字去找到对应的图标,再将它加载进去,这样就不会乱了
以上是内存溢出为你收集整理的基于Android Tv制作一个Tv桌面(三)全部内容,希望文章能够帮你解决基于Android Tv制作一个Tv桌面(三)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)