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>
網易雲ofollow,noindex" target="_blank">免費體驗館 ,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社群
相關文章:
【推薦】 Vuex實踐
【推薦】 HBase基準效能測試報告