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.v17.leanback.R; 19import android.support.v17.leanback.transition.TransitionHelper; 20import android.support.v17.leanback.widget.BrowseFrameLayout; 21import android.support.v17.leanback.widget.OnItemViewClickedListener; 22import android.support.v17.leanback.widget.OnItemViewSelectedListener; 23import android.support.v17.leanback.widget.Presenter; 24import android.support.v17.leanback.widget.Row; 25import android.support.v17.leanback.widget.RowPresenter; 26import android.support.v17.leanback.widget.TitleView; 27import android.support.v17.leanback.widget.VerticalGridPresenter; 28import android.support.v17.leanback.widget.ObjectAdapter; 29import android.support.v17.leanback.widget.OnItemClickedListener; 30import android.support.v17.leanback.widget.OnItemSelectedListener; 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 OnItemSelectedListener mOnItemSelectedListener; 62 private OnItemClickedListener mOnItemClickedListener; 63 private OnItemViewSelectedListener mOnItemViewSelectedListener; 64 private OnItemViewClickedListener mOnItemViewClickedListener; 65 private View.OnClickListener mExternalOnSearchClickedListener; 66 private int mSelectedPosition = -1; 67 68 private TitleView mTitleView; 69 private SearchOrbView.Colors mSearchAffordanceColors; 70 private boolean mSearchAffordanceColorSet; 71 private boolean mShowingTitle = true; 72 73 // transition related 74 private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance(); 75 private Object mTitleUpTransition; 76 private Object mTitleDownTransition; 77 private Object mSceneWithTitle; 78 private Object mSceneWithoutTitle; 79 80 /** 81 * Sets the badge drawable displayed in the title area. 82 */ 83 public void setBadgeDrawable(Drawable drawable) { 84 if (drawable != mBadgeDrawable) { 85 mBadgeDrawable = drawable; 86 if (mTitleView != null) { 87 mTitleView.setBadgeDrawable(drawable); 88 } 89 } 90 } 91 92 /** 93 * Returns the badge drawable. 94 */ 95 public Drawable getBadgeDrawable() { 96 return mBadgeDrawable; 97 } 98 99 /** 100 * Sets a title for the fragment. 101 */ 102 public void setTitle(String title) { 103 mTitle = title; 104 if (mTitleView != null) { 105 mTitleView.setTitle(mTitle); 106 } 107 } 108 109 /** 110 * Returns the title for the fragment. 111 */ 112 public String getTitle() { 113 return mTitle; 114 } 115 116 /** 117 * Sets the grid presenter. 118 */ 119 public void setGridPresenter(VerticalGridPresenter gridPresenter) { 120 if (gridPresenter == null) { 121 throw new IllegalArgumentException("Grid presenter may not be null"); 122 } 123 mGridPresenter = gridPresenter; 124 mGridPresenter.setOnItemViewSelectedListener(mRowSelectedListener); 125 if (mOnItemViewClickedListener != null) { 126 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 127 } 128 if (mOnItemClickedListener != null) { 129 mGridPresenter.setOnItemClickedListener(mOnItemClickedListener); 130 } 131 } 132 133 /** 134 * Returns the grid presenter. 135 */ 136 public VerticalGridPresenter getGridPresenter() { 137 return mGridPresenter; 138 } 139 140 /** 141 * Sets the object adapter for the fragment. 142 */ 143 public void setAdapter(ObjectAdapter adapter) { 144 mAdapter = adapter; 145 updateAdapter(); 146 } 147 148 /** 149 * Returns the object adapter. 150 */ 151 public ObjectAdapter getAdapter() { 152 return mAdapter; 153 } 154 155 final private OnItemViewSelectedListener mRowSelectedListener = 156 new OnItemViewSelectedListener() { 157 @Override 158 public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, 159 RowPresenter.ViewHolder rowViewHolder, Row row) { 160 int position = mGridViewHolder.getGridView().getSelectedPosition(); 161 if (DEBUG) Log.v(TAG, "row selected position " + position); 162 onRowSelected(position); 163 if (mOnItemSelectedListener != null) { 164 mOnItemSelectedListener.onItemSelected(item, row); 165 } 166 if (mOnItemViewSelectedListener != null) { 167 mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item, 168 rowViewHolder, row); 169 } 170 } 171 }; 172 173 /** 174 * Sets an item selection listener. 175 * @deprecated Use {@link #setOnItemViewSelectedListener(OnItemViewSelectedListener)} 176 */ 177 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 178 mOnItemSelectedListener = listener; 179 } 180 181 /** 182 * Sets an item selection listener. 183 */ 184 public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 185 mOnItemViewSelectedListener = listener; 186 } 187 188 private void onRowSelected(int position) { 189 if (position != mSelectedPosition) { 190 if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(position)) { 191 // if has no sibling in front of it, show title 192 if (!mShowingTitle) { 193 sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition); 194 mShowingTitle = true; 195 } 196 } else if (mShowingTitle) { 197 sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition); 198 mShowingTitle = false; 199 } 200 mSelectedPosition = position; 201 } 202 } 203 204 /** 205 * Sets an item clicked listener. 206 * @deprecated Use {@link #setOnItemViewClickedListener(OnItemViewClickedListener)} 207 */ 208 public void setOnItemClickedListener(OnItemClickedListener listener) { 209 mOnItemClickedListener = listener; 210 if (mGridPresenter != null) { 211 mGridPresenter.setOnItemClickedListener(mOnItemClickedListener); 212 } 213 } 214 215 /** 216 * Returns the item clicked listener. 217 * @deprecated Use {@link #getOnItemViewClickedListener()} 218 */ 219 public OnItemClickedListener getOnItemClickedListener() { 220 return mOnItemClickedListener; 221 } 222 223 /** 224 * Sets an item clicked listener. 225 */ 226 public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 227 mOnItemViewClickedListener = listener; 228 if (mGridPresenter != null) { 229 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 230 } 231 } 232 233 /** 234 * Returns the item clicked listener. 235 */ 236 public OnItemViewClickedListener getOnItemViewClickedListener() { 237 return mOnItemViewClickedListener; 238 } 239 240 /** 241 * Sets a click listener for the search affordance. 242 * 243 * <p>The presence of a listener will change the visibility of the search 244 * affordance in the title area. When set to non-null, the title area will 245 * contain a call to search action. 246 * 247 * <p>The listener's onClick method will be invoked when the user clicks on 248 * the search action. 249 * 250 * @param listener The listener to invoke when the search affordance is 251 * clicked, or null to hide the search affordance. 252 */ 253 public void setOnSearchClickedListener(View.OnClickListener listener) { 254 mExternalOnSearchClickedListener = listener; 255 if (mTitleView != null) { 256 mTitleView.setOnSearchClickedListener(listener); 257 } 258 } 259 260 /** 261 * Sets the {@link SearchOrbView.Colors} used to draw the search affordance. 262 */ 263 public void setSearchAffordanceColors(SearchOrbView.Colors colors) { 264 mSearchAffordanceColors = colors; 265 mSearchAffordanceColorSet = true; 266 if (mTitleView != null) { 267 mTitleView.setSearchAffordanceColors(mSearchAffordanceColors); 268 } 269 } 270 271 /** 272 * Returns the {@link SearchOrbView.Colors} used to draw the search affordance. 273 */ 274 public SearchOrbView.Colors getSearchAffordanceColors() { 275 if (mSearchAffordanceColorSet) { 276 return mSearchAffordanceColors; 277 } 278 if (mTitleView == null) { 279 throw new IllegalStateException("Fragment views not yet created"); 280 } 281 return mTitleView.getSearchAffordanceColors(); 282 } 283 284 /** 285 * Sets the color used to draw the search affordance. 286 * A default brighter color will be set by the framework. 287 * 288 * @param color The color to use for the search affordance. 289 */ 290 public void setSearchAffordanceColor(int color) { 291 setSearchAffordanceColors(new SearchOrbView.Colors(color)); 292 } 293 294 /** 295 * Returns the color used to draw the search affordance. 296 */ 297 public int getSearchAffordanceColor() { 298 return getSearchAffordanceColors().color; 299 } 300 301 private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener = 302 new BrowseFrameLayout.OnFocusSearchListener() { 303 @Override 304 public View onFocusSearch(View focused, int direction) { 305 if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction); 306 307 final View searchOrbView = mTitleView.getSearchAffordanceView(); 308 final boolean isRtl = ViewCompat.getLayoutDirection(focused) == 309 View.LAYOUT_DIRECTION_RTL; 310 final int forward = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT; 311 if (focused == searchOrbView && ( 312 direction == View.FOCUS_DOWN || direction == forward)) { 313 return mGridViewHolder.view; 314 315 } else if (focused != searchOrbView && searchOrbView.getVisibility() == View.VISIBLE 316 && direction == View.FOCUS_UP) { 317 return searchOrbView; 318 319 } else { 320 return null; 321 } 322 } 323 }; 324 325 @Override 326 public View onCreateView(LayoutInflater inflater, ViewGroup container, 327 Bundle savedInstanceState) { 328 ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment, 329 container, false); 330 331 mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame); 332 mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener); 333 334 mTitleView = (TitleView) root.findViewById(R.id.browse_title_group); 335 mTitleView.setBadgeDrawable(mBadgeDrawable); 336 mTitleView.setTitle(mTitle); 337 if (mSearchAffordanceColorSet) { 338 mTitleView.setSearchAffordanceColors(mSearchAffordanceColors); 339 } 340 if (mExternalOnSearchClickedListener != null) { 341 mTitleView.setOnSearchClickedListener(mExternalOnSearchClickedListener); 342 } 343 344 mSceneWithTitle = sTransitionHelper.createScene(root, new Runnable() { 345 @Override 346 public void run() { 347 mTitleView.setVisibility(View.VISIBLE); 348 } 349 }); 350 mSceneWithoutTitle = sTransitionHelper.createScene(root, new Runnable() { 351 @Override 352 public void run() { 353 mTitleView.setVisibility(View.INVISIBLE); 354 } 355 }); 356 Context context = getActivity(); 357 mTitleUpTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_out); 358 mTitleDownTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_in); 359 360 return root; 361 } 362 363 @Override 364 public void onViewCreated(View view, Bundle savedInstanceState) { 365 ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock); 366 mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock); 367 gridDock.addView(mGridViewHolder.view); 368 369 updateAdapter(); 370 } 371 372 @Override 373 public void onStart() { 374 super.onStart(); 375 mGridViewHolder.getGridView().requestFocus(); 376 } 377 378 @Override 379 public void onPause() { 380 mTitleView.enableAnimation(false); 381 super.onPause(); 382 } 383 384 @Override 385 public void onResume() { 386 super.onResume(); 387 mTitleView.enableAnimation(true); 388 } 389 390 @Override 391 public void onDestroyView() { 392 super.onDestroyView(); 393 mGridViewHolder = null; 394 } 395 396 /** 397 * Sets the selected item position. 398 */ 399 public void setSelectedPosition(int position) { 400 mSelectedPosition = position; 401 if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) { 402 mGridViewHolder.getGridView().setSelectedPositionSmooth(position); 403 } 404 } 405 406 private void updateAdapter() { 407 if (mGridViewHolder != null) { 408 mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter); 409 if (mSelectedPosition != -1) { 410 mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition); 411 } 412 } 413 } 414} 415