android tv
突然想写一篇博客,于是就产生了这篇博客。很多地方都没有理解源码也没有点进去看,所以之后也会继续修改补全。如果对你有一点帮助,或者说你有神马想法或者困惑都可以留言。
一直以来的习惯,拿到一个项目,我就会先去看清单文件,所以先分析一下清单文件吧。
<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.LEANBACK_LAUNCHER" /> //这个地方与手机端开发区别较大,这个主要是声明了这是一个TV项目,如果不加这个,那么运行在TV上时,是找不到这个应用的运行图标的 </intent-filter> </activity>
然后我就打开了MainActivity,然后我发现里面竟然是空的。随后我就打开了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。里面有四个方法,我们一一来分析一下。
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()); 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 i; for (i = 0; i < NUM_ROWS; i++) { if (i != 0) { collections.shuffle(list); //打乱list里的数据 } ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); //里面要传一个Persenter类型的,Persenter里面有三个抽象方法,复写了Adapter for (int j = 0; j < NUM_COLS; j++) { listRowAdapter.add(list.get(j % 5)); //添加Movie,产生页面右边的15个数据 } HeaderItem header = new HeaderItem(i, MovieList.MOVIE_CATEGORY[i]); //产生左边的标题数据 mRowsAdapter.add(new ListRow(header, listRowAdapter)); //listRowAdapter是页面右边的数据
// new ListRow(header, 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 = 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; ImageCardView cardView = (ImageCardView) viewHolder.view; Log.d(TAG, "onBindViewHolder"); if (movie.getCardImageUrl() != null) { cardView.setTitleText(movie.getTitle()); cardView.setcontentText(movie.getStudio()); cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT); glide.with(viewHolder.view.getContext()) .load(movie.getCardImageUrl()) .centerCrop() .error(mDefaultCardImage) .into(cardView.getMainImageView()); } } @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(); } }); setOnItemViewClickedListener(new ItemViewClickedListener()); setOnItemViewSelectedListener(new ItemViewSelectedListener()); }这次就先写到这了
相关阅读
一.概念 在Android设备shell终端可以看到/system目录下的build.prop文件,android的build.prop文件是在Android编译时刻收集的
有很多场景和需求你需要用到手机设备的唯一标识符。在Android中,有以下几种方法获取这样的ID。1. The IMEI: 仅仅只对Android手机
一、效果图展示如果动图没有动的话,也可以看下面这个静态图以下挨个分析每个的实现,这里只做简单的效果展示,大家可以基于目前代码做
stdafx是预编译头文件,在其中包含的头文件之外第一次编译时编译,之后若不修改,不会再编译这些头文件,加快了编译的速度。targetver定
此前星海音乐学院女大学生岑斯婷家人报警称其面试失联,面试失联女大学生已现身 因涉嫌违法犯罪被刑拘,知情者:KTV兼职时获涉黄被抓!5