VerticalGridSupportFragment.java revision 70acb0c19be3831a2080e4f902324de16bfbf62e
1/* This file is auto-generated from VerticalGridFragment.java. DO NOT MODIFY. */ 2 3/* 4 * Copyright (C) 2014 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 7 * in compliance with the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software distributed under the License 12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 13 * or implied. See the License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.support.v17.leanback.app; 17 18import android.support.annotation.ColorInt; 19import android.support.v17.leanback.R; 20import android.support.v17.leanback.transition.TransitionHelper; 21import android.support.v17.leanback.widget.BrowseFrameLayout; 22import android.support.v17.leanback.widget.OnChildLaidOutListener; 23import android.support.v17.leanback.widget.OnItemViewClickedListener; 24import android.support.v17.leanback.widget.OnItemViewSelectedListener; 25import android.support.v17.leanback.widget.Presenter; 26import android.support.v17.leanback.widget.Row; 27import android.support.v17.leanback.widget.RowPresenter; 28import android.support.v17.leanback.widget.TitleView; 29import android.support.v17.leanback.widget.VerticalGridPresenter; 30import android.support.v17.leanback.widget.ObjectAdapter; 31import android.support.v17.leanback.widget.SearchOrbView; 32import android.support.v4.view.ViewCompat; 33import android.support.v4.app.Fragment; 34import android.content.Context; 35import android.graphics.drawable.Drawable; 36import android.os.Bundle; 37import android.util.Log; 38import android.view.LayoutInflater; 39import android.view.View; 40import android.view.ViewGroup; 41import android.view.ViewGroup.MarginLayoutParams; 42import android.widget.ImageView; 43import android.widget.TextView; 44 45/** 46 * A fragment for creating leanback vertical grids. 47 * 48 * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and 49 * an {@link ObjectAdapter}. 50 */ 51public class VerticalGridSupportFragment extends Fragment { 52 private static final String TAG = "VerticalGridSupportFragment"; 53 private static boolean DEBUG = false; 54 55 private BrowseFrameLayout mBrowseFrame; 56 private String mTitle; 57 private Drawable mBadgeDrawable; 58 private ObjectAdapter mAdapter; 59 private VerticalGridPresenter mGridPresenter; 60 private VerticalGridPresenter.ViewHolder mGridViewHolder; 61 private OnItemViewSelectedListener mOnItemViewSelectedListener; 62 private OnItemViewClickedListener mOnItemViewClickedListener; 63 private View.OnClickListener mExternalOnSearchClickedListener; 64 private int mSelectedPosition = -1; 65 66 private TitleView mTitleView; 67 private SearchOrbView.Colors mSearchAffordanceColors; 68 private boolean mSearchAffordanceColorSet; 69 private boolean mShowingTitle = true; 70 71 // transition related 72 private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance(); 73 private Object mTitleUpTransition; 74 private Object mTitleDownTransition; 75 private Object mSceneWithTitle; 76 private Object mSceneWithoutTitle; 77 78 /** 79 * Sets the badge drawable displayed in the title area. 80 */ 81 public void setBadgeDrawable(Drawable drawable) { 82 if (drawable != mBadgeDrawable) { 83 mBadgeDrawable = drawable; 84 if (mTitleView != null) { 85 mTitleView.setBadgeDrawable(drawable); 86 } 87 } 88 } 89 90 /** 91 * Returns the badge drawable. 92 */ 93 public Drawable getBadgeDrawable() { 94 return mBadgeDrawable; 95 } 96 97 /** 98 * Sets a title for the fragment. 99 */ 100 public void setTitle(String title) { 101 mTitle = title; 102 if (mTitleView != null) { 103 mTitleView.setTitle(mTitle); 104 } 105 } 106 107 /** 108 * Returns the title for the fragment. 109 */ 110 public String getTitle() { 111 return mTitle; 112 } 113 114 /** 115 * Sets the grid presenter. 116 */ 117 public void setGridPresenter(VerticalGridPresenter gridPresenter) { 118 if (gridPresenter == null) { 119 throw new IllegalArgumentException("Grid presenter may not be null"); 120 } 121 mGridPresenter = gridPresenter; 122 mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener); 123 if (mOnItemViewClickedListener != null) { 124 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 125 } 126 } 127 128 /** 129 * Returns the grid presenter. 130 */ 131 public VerticalGridPresenter getGridPresenter() { 132 return mGridPresenter; 133 } 134 135 /** 136 * Sets the object adapter for the fragment. 137 */ 138 public void setAdapter(ObjectAdapter adapter) { 139 mAdapter = adapter; 140 updateAdapter(); 141 } 142 143 /** 144 * Returns the object adapter. 145 */ 146 public ObjectAdapter getAdapter() { 147 return mAdapter; 148 } 149 150 final private OnItemViewSelectedListener mViewSelectedListener = 151 new OnItemViewSelectedListener() { 152 @Override 153 public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, 154 RowPresenter.ViewHolder rowViewHolder, Row row) { 155 int position = mGridViewHolder.getGridView().getSelectedPosition(); 156 if (DEBUG) Log.v(TAG, "grid selected position " + position); 157 gridOnItemSelected(position); 158 if (mOnItemViewSelectedListener != null) { 159 mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item, 160 rowViewHolder, row); 161 } 162 } 163 }; 164 165 final private OnChildLaidOutListener mChildLaidOutListener = 166 new OnChildLaidOutListener() { 167 @Override 168 public void onChildLaidOut(ViewGroup parent, View view, int position, long id) { 169 if (position == 0) { 170 showOrHideTitle(); 171 } 172 } 173 }; 174 175 /** 176 * Sets an item selection listener. 177 */ 178 public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 179 mOnItemViewSelectedListener = listener; 180 } 181 182 private void gridOnItemSelected(int position) { 183 if (position != mSelectedPosition) { 184 mSelectedPosition = position; 185 showOrHideTitle(); 186 } 187 } 188 189 private void showOrHideTitle() { 190 if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition) 191 == null) { 192 return; 193 } 194 if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) { 195 // if has no sibling in front of it, show title 196 if (!mShowingTitle) { 197 sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition); 198 mShowingTitle = true; 199 } 200 } else if (mShowingTitle) { 201 sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition); 202 mShowingTitle = false; 203 } 204 } 205 206 /** 207 * Sets an item clicked listener. 208 */ 209 public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 210 mOnItemViewClickedListener = listener; 211 if (mGridPresenter != null) { 212 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 213 } 214 } 215 216 /** 217 * Returns the item clicked listener. 218 */ 219 public OnItemViewClickedListener getOnItemViewClickedListener() { 220 return mOnItemViewClickedListener; 221 } 222 223 /** 224 * Sets a click listener for the search affordance. 225 * 226 * <p>The presence of a listener will change the visibility of the search 227 * affordance in the title area. When set to non-null, the title area will 228 * contain a call to search action. 229 * 230 * <p>The listener's onClick method will be invoked when the user clicks on 231 * the search action. 232 * 233 * @param listener The listener to invoke when the search affordance is 234 * clicked, or null to hide the search affordance. 235 */ 236 public void setOnSearchClickedListener(View.OnClickListener listener) { 237 mExternalOnSearchClickedListener = listener; 238 if (mTitleView != null) { 239 mTitleView.setOnSearchClickedListener(listener); 240 } 241 } 242 243 /** 244 * Sets the {@link SearchOrbView.Colors} used to draw the search affordance. 245 */ 246 public void setSearchAffordanceColors(SearchOrbView.Colors colors) { 247 mSearchAffordanceColors = colors; 248 mSearchAffordanceColorSet = true; 249 if (mTitleView != null) { 250 mTitleView.setSearchAffordanceColors(mSearchAffordanceColors); 251 } 252 } 253 254 /** 255 * Returns the {@link SearchOrbView.Colors} used to draw the search affordance. 256 */ 257 public SearchOrbView.Colors getSearchAffordanceColors() { 258 if (mSearchAffordanceColorSet) { 259 return mSearchAffordanceColors; 260 } 261 if (mTitleView == null) { 262 throw new IllegalStateException("Fragment views not yet created"); 263 } 264 return mTitleView.getSearchAffordanceColors(); 265 } 266 267 /** 268 * Sets the color used to draw the search affordance. 269 * A default brighter color will be set by the framework. 270 * 271 * @param color The color to use for the search affordance. 272 */ 273 public void setSearchAffordanceColor(@ColorInt int color) { 274 setSearchAffordanceColors(new SearchOrbView.Colors(color)); 275 } 276 277 /** 278 * Returns the color used to draw the search affordance. 279 */ 280 @ColorInt 281 public int getSearchAffordanceColor() { 282 return getSearchAffordanceColors().color; 283 } 284 285 private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener = 286 new BrowseFrameLayout.OnFocusSearchListener() { 287 @Override 288 public View onFocusSearch(View focused, int direction) { 289 if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction); 290 291 final View searchOrbView = mTitleView.getSearchAffordanceView(); 292 final boolean isRtl = ViewCompat.getLayoutDirection(focused) == 293 View.LAYOUT_DIRECTION_RTL; 294 final int forward = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT; 295 if (focused == searchOrbView && ( 296 direction == View.FOCUS_DOWN || direction == forward)) { 297 return mGridViewHolder.view; 298 299 } else if (focused != searchOrbView && searchOrbView.getVisibility() == View.VISIBLE 300 && direction == View.FOCUS_UP) { 301 return searchOrbView; 302 303 } else { 304 return null; 305 } 306 } 307 }; 308 309 @Override 310 public View onCreateView(LayoutInflater inflater, ViewGroup container, 311 Bundle savedInstanceState) { 312 ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment, 313 container, false); 314 315 mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame); 316 mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener); 317 318 mTitleView = (TitleView) root.findViewById(R.id.browse_title_group); 319 mTitleView.setBadgeDrawable(mBadgeDrawable); 320 mTitleView.setTitle(mTitle); 321 if (mSearchAffordanceColorSet) { 322 mTitleView.setSearchAffordanceColors(mSearchAffordanceColors); 323 } 324 if (mExternalOnSearchClickedListener != null) { 325 mTitleView.setOnSearchClickedListener(mExternalOnSearchClickedListener); 326 } 327 328 mSceneWithTitle = sTransitionHelper.createScene(root, new Runnable() { 329 @Override 330 public void run() { 331 mTitleView.setVisibility(View.VISIBLE); 332 } 333 }); 334 mSceneWithoutTitle = sTransitionHelper.createScene(root, new Runnable() { 335 @Override 336 public void run() { 337 mTitleView.setVisibility(View.INVISIBLE); 338 } 339 }); 340 Context context = getActivity(); 341 mTitleUpTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_out); 342 mTitleDownTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_in); 343 344 return root; 345 } 346 347 @Override 348 public void onViewCreated(View view, Bundle savedInstanceState) { 349 ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock); 350 mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock); 351 gridDock.addView(mGridViewHolder.view); 352 mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener); 353 354 updateAdapter(); 355 } 356 357 @Override 358 public void onStart() { 359 super.onStart(); 360 mGridViewHolder.getGridView().requestFocus(); 361 } 362 363 @Override 364 public void onPause() { 365 mTitleView.enableAnimation(false); 366 super.onPause(); 367 } 368 369 @Override 370 public void onResume() { 371 super.onResume(); 372 mTitleView.enableAnimation(true); 373 } 374 375 @Override 376 public void onDestroyView() { 377 super.onDestroyView(); 378 mGridViewHolder = null; 379 } 380 381 /** 382 * Sets the selected item position. 383 */ 384 public void setSelectedPosition(int position) { 385 mSelectedPosition = position; 386 if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) { 387 mGridViewHolder.getGridView().setSelectedPositionSmooth(position); 388 } 389 } 390 391 private void updateAdapter() { 392 if (mGridViewHolder != null) { 393 mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter); 394 if (mSelectedPosition != -1) { 395 mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition); 396 } 397 } 398 } 399} 400