120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/* 220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Copyright (C) 2014 The Android Open Source Project 320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * in compliance with the License. You may obtain a copy of the License at 620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * http://www.apache.org/licenses/LICENSE-2.0 820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Unless required by applicable law or agreed to in writing, software distributed under the License 1020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * or implied. See the License for the specific language governing permissions and limitations under 1220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * the License. 1320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 1420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournpackage android.support.v17.leanback.widget; 1520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 1620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.view.View; 1720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.view.ViewGroup; 1820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 1920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/** 2020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * A Presenter is used to generate {@link View}s and bind Objects to them on 2160d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * demand. It is closely related to concept of an {@link 2260d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, but is 2360d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * not position-based. 2420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 2520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * <p> 2620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * A trivial Presenter that takes a string and renders it into a {@link 2760d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * android.widget.TextView TextView}: 2820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 2920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * <pre class="prettyprint"> 3020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * public class StringTextViewPresenter extends Presenter { 3120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * // This class does not need a custom ViewHolder, since it does not use 3220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * // a complex layout. 3320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 3420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 3560d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public ViewHolder onCreateViewHolder(ViewGroup parent) { 3620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * return new ViewHolder(new TextView(parent.getContext())); 3720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 3820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 3920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 4060d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public void onBindViewHolder(ViewHolder viewHolder, Object item) { 4120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * String str = (String) item; 4220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * TextView textView = (TextView) viewHolder.mView; 4320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 4420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * textView.setText(item); 4520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 4620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 4720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 4860d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public void onUnbindViewHolder(ViewHolder viewHolder) { 4960d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * // Nothing to unbind for TextView, but if this viewHolder had 5060d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * // allocated bitmaps, they can be released here. 5120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 5220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 5320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * </pre> 5420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 5520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournpublic abstract class Presenter { 5620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 5720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * ViewHolder can be subclassed and used to cache any view accessors needed 5820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * to improve binding performance (for example, results of findViewById) 5920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * without needing to subclass a View. 6020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 6120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public static class ViewHolder { 6220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public final View view; 6320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 6420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public ViewHolder(View view) { 6520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn this.view = view; 6620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 6720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 6820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 6920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 7020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Creates a new {@link View}. 7120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 7220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract ViewHolder onCreateViewHolder(ViewGroup parent); 7320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 7420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 7520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Binds a {@link View} to an item. 7620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 7720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract void onBindViewHolder(ViewHolder viewHolder, Object item); 7820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 7920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 8020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Unbinds a {@link View} from an item. Any expensive references may be 8120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * released here, and any fields that are not bound for every item should be 8220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * cleared here. 8320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 8420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract void onUnbindViewHolder(ViewHolder viewHolder); 8547520b68e50572a9775a662410c5aff8300c8784Craig Stout 8647520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 8747520b68e50572a9775a662410c5aff8300c8784Craig Stout * Called when a view created by this presenter has been attached to a window. 8847520b68e50572a9775a662410c5aff8300c8784Craig Stout * 8947520b68e50572a9775a662410c5aff8300c8784Craig Stout * <p>This can be used as a reasonable signal that the view is about to be seen 9047520b68e50572a9775a662410c5aff8300c8784Craig Stout * by the user. If the adapter previously freed any resources in 9147520b68e50572a9775a662410c5aff8300c8784Craig Stout * {@link #onViewDetachedFromWindow(ViewHolder)} 9247520b68e50572a9775a662410c5aff8300c8784Craig Stout * those resources should be restored here.</p> 9347520b68e50572a9775a662410c5aff8300c8784Craig Stout * 9447520b68e50572a9775a662410c5aff8300c8784Craig Stout * @param holder Holder of the view being attached 9547520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 9647520b68e50572a9775a662410c5aff8300c8784Craig Stout public void onViewAttachedToWindow(ViewHolder holder) { 9747520b68e50572a9775a662410c5aff8300c8784Craig Stout } 9847520b68e50572a9775a662410c5aff8300c8784Craig Stout 9947520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 10047520b68e50572a9775a662410c5aff8300c8784Craig Stout * Called when a view created by this presenter has been detached from its window. 10147520b68e50572a9775a662410c5aff8300c8784Craig Stout * 10247520b68e50572a9775a662410c5aff8300c8784Craig Stout * <p>Becoming detached from the window is not necessarily a permanent condition; 10347520b68e50572a9775a662410c5aff8300c8784Craig Stout * the consumer of an presenter's views may choose to cache views offscreen while they 10447520b68e50572a9775a662410c5aff8300c8784Craig Stout * are not visible, attaching an detaching them as appropriate.</p> 10547520b68e50572a9775a662410c5aff8300c8784Craig Stout * 1065358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * Any view property animations should be cancelled here or the view may fail 1075358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * to be recycled. 1085358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * 10947520b68e50572a9775a662410c5aff8300c8784Craig Stout * @param holder Holder of the view being detached 11047520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 11147520b68e50572a9775a662410c5aff8300c8784Craig Stout public void onViewDetachedFromWindow(ViewHolder holder) { 1125358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout // If there are view property animations running then RecyclerView won't recycle. 1135358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout cancelAnimationsRecursive(holder.view); 1145358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1155358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout 1165358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout /** 1175358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * Utility method for removing all running animations on a view. 1185358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout */ 1195358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout protected static void cancelAnimationsRecursive(View view) { 1205358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout if (view.hasTransientState()) { 1215358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout view.animate().cancel(); 1225358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout if (view instanceof ViewGroup) { 1235358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout final int count = ((ViewGroup) view).getChildCount(); 1245358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout for (int i = 0; view.hasTransientState() && i < count; i++) { 1255358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout cancelAnimationsRecursive(((ViewGroup) view).getChildAt(i)); 1265358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1275358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1285358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 12947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 13047520b68e50572a9775a662410c5aff8300c8784Craig Stout 1317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout /** 1327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Called to set a click listener for the given view holder. 1337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * 1347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * The default implementation sets the click listener on the root view in the view holder. 1357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * If the root view isn't focusable this method should be overridden to set the listener 1367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * on the appropriate focusable child view(s). 1377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * 1387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * @param holder The view holder containing the view(s) on which the listener should be set. 1397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * @param listener The click listener to be set. 1407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */ 1417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout public void setOnClickListener(ViewHolder holder, View.OnClickListener listener) { 1427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout holder.view.setOnClickListener(listener); 1437ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout } 14420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn} 145