• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.menu;
18 
19 import android.content.Context;
20 import android.support.v17.leanback.widget.HorizontalGridView;
21 import android.support.v17.leanback.widget.OnChildSelectedListener;
22 import android.support.v7.widget.RecyclerView;
23 import android.util.AttributeSet;
24 import android.util.Log;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.view.ViewGroup;
28 
29 import com.android.tv.MainActivity;
30 import com.android.tv.R;
31 
32 import java.util.Collections;
33 import java.util.List;
34 
35 /**
36  * A view that shows a title and list view.
37  */
38 public class ItemListRowView extends MenuRowView implements OnChildSelectedListener {
39     private static final String TAG = MenuView.TAG;
40     private static final boolean DEBUG = MenuView.DEBUG;
41 
42     public interface CardView<T> {
onBind(T row, boolean selected)43         void onBind(T row, boolean selected);
onRecycled()44         void onRecycled();
onSelected()45         void onSelected();
onDeselected()46         void onDeselected();
47     }
48 
49     private HorizontalGridView mListView;
50     private CardView<?> mSelectedCard;
51 
ItemListRowView(Context context)52     public ItemListRowView(Context context) {
53         this(context, null);
54     }
55 
ItemListRowView(Context context, AttributeSet attrs)56     public ItemListRowView(Context context, AttributeSet attrs) {
57         this(context, attrs, 0);
58     }
59 
ItemListRowView(Context context, AttributeSet attrs, int defStyle)60     public ItemListRowView(Context context, AttributeSet attrs, int defStyle) {
61         this(context, attrs, defStyle, 0);
62     }
63 
ItemListRowView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)64     public ItemListRowView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
65         super(context, attrs, defStyleAttr, defStyleRes);
66     }
67 
68     @Override
onFinishInflate()69     protected void onFinishInflate() {
70         super.onFinishInflate();
71         mListView = (HorizontalGridView) getContentsView();
72     }
73 
74     @Override
getContentsViewId()75     protected int getContentsViewId() {
76         return R.id.list_view;
77     }
78 
79     @Override
onBind(MenuRow row)80     public void onBind(MenuRow row) {
81         super.onBind(row);
82         ItemListAdapter<?> adapter = ((ItemListRow) row).getAdapter();
83         adapter.mItemListView = this;
84 
85         mListView.setOnChildSelectedListener(this);
86         mListView.setAdapter(adapter);
87     }
88 
89     @Override
initialize(int reason)90     public void initialize(int reason) {
91         super.initialize(reason);
92         setInitialFocusView(mListView);
93         mListView.setSelectedPosition(getAdapter().getInitialPosition());
94     }
95 
getAdapter()96     private ItemListAdapter<?> getAdapter() {
97         return (ItemListAdapter<?>) mListView.getAdapter();
98     }
99 
100     @Override
onChildSelected(ViewGroup parent, View child, int position, long id)101     public void onChildSelected(ViewGroup parent, View child, int position, long id) {
102         if (DEBUG) Log.d(TAG, "onChildSelected: child=" + child);
103         if (mSelectedCard == child) {
104             return;
105         }
106         if (mSelectedCard != null) {
107             mSelectedCard.onDeselected();
108         }
109         mSelectedCard = (CardView<?>) child;
110         if (mSelectedCard != null) {
111             mSelectedCard.onSelected();
112         }
113     }
114 
115     public static abstract class ItemListAdapter<T>
116             extends RecyclerView.Adapter<ItemListAdapter.MyViewHolder> {
117         private final MainActivity mMainActivity;
118         private final LayoutInflater mLayoutInflater;
119         private List<T> mItemList = Collections.emptyList();
120         private ItemListRowView mItemListView;
121 
ItemListAdapter(Context context)122         public ItemListAdapter(Context context) {
123             // Only MainActivity can use the main menu.
124             mMainActivity = (MainActivity) context;
125             mLayoutInflater = LayoutInflater.from(context);
126         }
127 
128         /**
129          * In most cases, implementation should call {@link #setItemList(java.util.List)} with
130          * newly update item list.
131          */
update()132         public abstract void update();
133 
134         /**
135          * Gets layout resource ID. It'll be used in {@link #onCreateViewHolder}.
136          */
getLayoutResId(int viewType)137         protected abstract int getLayoutResId(int viewType);
138 
139         /**
140          * Releases all the resources which need to be released.
141         */
release()142         public void release() {
143         }
144 
145         /**
146          * The initial position of list that will be selected when the main menu appears.
147          * By default, the first item is initially selected.
148          */
getInitialPosition()149         public int getInitialPosition() {
150             return 0;
151         }
152 
153         /** The MainActivity that the corresponding ItemListView belongs to. */
getMainActivity()154         protected MainActivity getMainActivity() {
155             return mMainActivity;
156         }
157 
158         /** The item list. */
getItemList()159         protected List<T> getItemList() {
160             return mItemList;
161         }
162 
163         /**
164          * Sets the item list.
165          *
166          * <p>This sends an item change event, not a structural change event. The items of the same
167          * positions retain the same identity.
168          *
169          * <p>If there's any structural change and relayout and rebind is needed, call
170          * {@link #notifyDataSetChanged} explicitly.
171          */
setItemList(List<T> itemList)172         protected void setItemList(List<T> itemList) {
173             int oldSize = mItemList.size();
174             int newSize = itemList.size();
175             mItemList = itemList;
176             if (oldSize > newSize) {
177                 notifyItemRangeChanged(0, newSize);
178                 notifyItemRangeRemoved(newSize, oldSize - newSize);
179             } else if (oldSize < newSize) {
180                 notifyItemRangeChanged(0, oldSize);
181                 notifyItemRangeInserted(oldSize, newSize - oldSize);
182             } else {
183                 notifyItemRangeChanged(0, oldSize);
184             }
185         }
186 
187         @Override
getItemViewType(int position)188         public int getItemViewType(int position) {
189             return 0;
190         }
191 
192         @Override
getItemCount()193         public int getItemCount() {
194             return mItemList.size();
195         }
196 
197         @Override
onCreateViewHolder(ViewGroup parent, int viewType)198         public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
199             View view = mLayoutInflater.inflate(getLayoutResId(viewType), parent, false);
200             return new MyViewHolder(view);
201         }
202 
203         @Override
onBindViewHolder(MyViewHolder viewHolder, int position)204         public void onBindViewHolder(MyViewHolder viewHolder, int position) {
205             @SuppressWarnings("unchecked")
206             CardView<T> cardView = (CardView<T>) viewHolder.itemView;
207             cardView.onBind(mItemList.get(position), cardView.equals(mItemListView.mSelectedCard));
208         }
209 
210         @Override
onViewRecycled(MyViewHolder viewHolder)211         public void onViewRecycled(MyViewHolder viewHolder) {
212             super.onViewRecycled(viewHolder);
213             CardView<T> cardView = (CardView<T>) viewHolder.itemView;
214             cardView.onRecycled();
215         }
216 
217         public static class MyViewHolder extends RecyclerView.ViewHolder {
MyViewHolder(View view)218             public MyViewHolder(View view) {
219                 super(view);
220             }
221         }
222     }
223 }
224