Android TV 开发(4)
本文来自网易云社区
作者:孙有军
最后我们再来看看好友界面,改界面本地是没有xml的,因此我们直接来看看代码:
这里将使用到数据bean,与数据源的代码也贴出来如下:
public class Contact implements Parcelable { private String phone; private int headResId; private String name; public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public int getHeadResId() { return headResId; } public void setHeadResId(int headResId) { this.headResId = headResId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Contact() { } public Contact(Parcel in) { phone = in.readString(); headResId = in.readInt(); name = in.readString(); } public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(phone); dest.writeInt(headResId); dest.writeString(name); } @Override public String toString() { StringBuilder sb = new StringBuilder(200); sb.append("Contact{"); sb.append("phone='" + phone + '\''); sb.append(", headResId='" + headResId + '\''); sb.append(", name='" + name + '\''); sb.append('}'); return sb.toString(); } public static final Creator CREATOR = new Creator() { public Contact createFromParcel(Parcel in) { return new Contact(in); } public Contact[] newArray(int size) { return new Contact[size]; } }; } ////// public class ContactProvider { private static List<Contact> contactList; private static Context sContext; private static int[] head = {R.drawable.avater1, R.drawable.avater2, R.drawable.avater3, R.drawable.avater4, R .drawable.avater5, R.drawable.avater6, R.drawable.avater7, R.drawable.avater8, R.drawable.avater9, R .drawable.avater10, R.drawable.avater11, R.drawable.avater12}; private static String[] names = {"梦洁", "雅静", "韵寒", "莉姿", "沛玲", "欣妍", "歆瑶", "凌菲", "靖瑶", "瑾萱", "芳蕤", "若华"}; private static String[] phones = {"18618188630", "18158103936", "18620145337", "15116333186", "18618188630", "18158103936", "18620145337", "15116333186", "18618188630", "18158103936", "18620145337", "18767106408"}; public static void setContext(Context context) { if (sContext == null) sContext = context; } public static List<Contact> getContactList() { buildContact(); return contactList; } public static List<Contact> buildContact() { if (null != contactList) { return contactList; } contactList = new ArrayList<Contact>(); for (int i = 0; i < 12; ++i) { contactList.add(buildContactInfo(phones[i], names[i], head[i])); } return contactList; } private static Contact buildContactInfo(String phone, String name, int resId) { Contact contact = new Contact(); contact.setPhone(phone); contact.setName(name); contact.setHeadResId(resId); return contact; } }
/* * VerticalGridFragment shows a grid of videos */ public class VerticalGridFragment extends android.support.v17.leanback.app.VerticalGridFragment { private static final String TAG = "VerticalGridFragment"; private static final int DEFAULT_COLUMNS = 4; private int numColumns = DEFAULT_COLUMNS; private ArrayObjectAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate"); super.onCreate(savedInstanceState); //setTitle(getString(R.string.vertical_grid_title)); getParams(); setupFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = super.onCreateView(inflater, container, savedInstanceState); return root; } private void setupFragment() { VerticalGridPresenter gridPresenter = new VerticalGridPresenter(FocusHighlight.ZOOM_FACTOR_NONE); gridPresenter.setNumberOfColumns(numColumns); //gridPresenter.setShadowEnabled(false); setGridPresenter(gridPresenter); mAdapter = new ArrayObjectAdapter(new ContactPresenter()); List<Contact> contacts = ContactProvider.getContactList(); mAdapter.addAll(0, contacts); setAdapter(mAdapter); setOnItemViewClickedListener(new ItemViewClickedListener()); setOnItemViewSelectedListener(new ItemViewSelectedListener()); } public void getParams() { if (getArguments() != null) { numColumns = getArguments().getInt(Extra.COLUMNS); } } private final class ItemViewClickedListener implements OnItemViewClickedListener { @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { if (item instanceof Contact) { Contact contact = (Contact) item; // TODO } } } private final class ItemViewSelectedListener implements OnItemViewSelectedListener { @Override public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { } } }
在Fragment中我们自己实现了一个ContactPresenter,该Presenter是仿照官方的CardPresenter,但是CardPresenter中使用的ImageCardView是系统support包中提供的控件,而ContactPresenter中使用的是自己自定义的控件, 代码如下:
public class ContactPresenter extends Presenter { private static final String TAG = "CardPresenter"; private static int sSelectedBackgroundColor; private static int sDefaultBackgroundColor; @Override public ViewHolder onCreateViewHolder(ViewGroup parent) { Log.d(TAG, "onCreateViewHolder"); sDefaultBackgroundColor = parent.getResources().getColor(R.color.white_35_transparent); sSelectedBackgroundColor = parent.getResources().getColor(R.color.white_60_transparent); ContactView contactView = new ContactView(parent.getContext()) { @Override public void setSelected(boolean selected) { updateCardBackgroundColor(this, selected); super.setSelected(selected); } }; contactView.setFocusable(true); contactView.setFocusableInTouchMode(true); updateCardBackgroundColor(contactView, false); return new ViewHolder(contactView); } private static void updateCardBackgroundColor(ContactView view, boolean selected) { int color = selected ? sSelectedBackgroundColor : sDefaultBackgroundColor; view.setBackgroundColor(color); //view.findViewById(R.id.info_field).setBackgroundColor(color); } @Override public void onBindViewHolder(ViewHolder viewHolder, Object item) { Contact contact = (Contact) item; ContactView contactView = (ContactView) viewHolder.view; Log.d(TAG, "onBindViewHolder"); contactView.setHead(contact.getHeadResId()); contactView.setName(contact.getName()); contactView.setPhone(contact.getPhone()); } @Override public void onUnbindViewHolder(ViewHolder viewHolder) { Log.d(TAG, "onUnbindViewHolder"); ContactView contactView = (ContactView) viewHolder.view; // Remove references to images so that the garbage collector can free up memory contactView.setHead(0); } }
ContactView是一个继承自LinearLayout的自定义控件,包含了一个ImageView和两个TextView。
到此整个界面的代码就完成了,接下来我们来看看遇到的问题。
问题列表
问题1:控件遥控器不能选中,不能导航
出现这种问题往往是控件没有设置android:focusable="true"属性,只有默认能够选中焦点的才不需要设置改属性,比如Button,EditText。
问题2:控件选中后,看不出选中效果
由于默认选中是没有视觉效果的,因此你需要对控件设置选中效果,比如说背景图片,以前在手机上可能只需要设置selector中的pressed属性,或者selected属性,现在针对TV你必须要设置focused属性,比如拨号键盘选中后会出现一个圆形的选中背景框,
要实现上述效果,因此对每一键盘输入按钮添加如下的selector。
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/key_board_hover" android:state_focused="true"></item> <item android:drawable="@drawable/key_board_hover" android:state_pressed="true"></item> <item android:drawable="@drawable/key_board_hover" android:state_checked="true"></item> <item android:drawable="@color/transparent"></item> </selector> key_board_hover.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/white_35_transparent"></solid> <size android:width="40dp" android:height="40dp"/> </shape>
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区
相关文章:
【推荐】 对云环境下访问控制系统的思考
【推荐】 交互设计如何为业务赋能——谈谈网易严选企业采购的主页设计