RowsSupportFragment.java revision 61905b0b52c50018dcaebcd79699c39b8f28d622
161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/* 261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Copyright (C) 2014 The Android Open Source Project 361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * in compliance with the License. You may obtain a copy of the License at 661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 1061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 1261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the License. 1361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 1461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupackage android.support.v17.leanback.app; 1561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport java.util.ArrayList; 1761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.TimeAnimator; 1961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.TimeAnimator.TimeListener; 2061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Bundle; 2161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R; 2261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ItemBridgeAdapter; 2361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener; 2461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener; 2561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter.ViewHolder; 2661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView; 2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.HorizontalGridView; 2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemSelectedListener; 2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemClickedListener; 3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter; 3161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ListRowPresenter; 3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter; 3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v7.widget.RecyclerView; 3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log; 3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View; 3661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup; 3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewTreeObserver; 3861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.animation.DecelerateInterpolator; 3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.animation.Interpolator; 4061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/** 4261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * An ordered set of rows of leanback widgets. 4361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupublic class RowsSupportFragment extends BaseRowSupportFragment { 4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Internal helper class that manages row select animation and apply a default 4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * dim to each row. 4961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final class RowViewHolderExtra implements TimeListener { 5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final RowPresenter mRowPresenter; 5261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final Presenter.ViewHolder mRowViewHolder; 5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 5461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final TimeAnimator mSelectAnimator = new TimeAnimator(); 5561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 5661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int mSelectAnimatorDurationInUse; 5761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu Interpolator mSelectAnimatorInterpolatorInUse; 5861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu float mSelectLevelAnimStart; 5961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu float mSelectLevelAnimDelta; 6061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 6161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowViewHolderExtra(ItemBridgeAdapter.ViewHolder ibvh) { 6261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowPresenter = (RowPresenter) ibvh.getPresenter(); 6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowViewHolder = ibvh.getViewHolder(); 6461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimator.setTimeListener(this); 6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 6661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 6961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectAnimator.isRunning()) { 7061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu updateSelect(totalTime, deltaTime); 7161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 7261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 7361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void updateSelect(long totalTime, long deltaTime) { 7561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu float fraction; 7661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (totalTime >= mSelectAnimatorDurationInUse) { 7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu fraction = 1; 7861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimator.end(); 7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu fraction = (float) (totalTime / (double) mSelectAnimatorDurationInUse); 8161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectAnimatorInterpolatorInUse != null) { 8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu fraction = mSelectAnimatorInterpolatorInUse.getInterpolation(fraction); 8461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu float level = mSelectLevelAnimStart + fraction * mSelectLevelAnimDelta; 8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowPresenter.setSelectLevel(mRowViewHolder, level); 8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void animateSelect(boolean select, boolean immediate) { 9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu endSelectAnimation(); 9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final float end = select ? 1 : 0; 9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (immediate) { 9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowPresenter.setSelectLevel(mRowViewHolder, end); 9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else if (mRowPresenter.getSelectLevel(mRowViewHolder) != end) { 9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimatorDurationInUse = mSelectAnimatorDuration; 9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimatorInterpolatorInUse = mSelectAnimatorInterpolator; 9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectLevelAnimStart = mRowPresenter.getSelectLevel(mRowViewHolder); 9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectLevelAnimDelta = end - mSelectLevelAnimStart; 9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimator.start(); 10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void endAnimations() { 10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu endSelectAnimation(); 10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void endSelectAnimation() { 10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimator.end(); 10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static final String TAG = "RowsSupportFragment"; 11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static final boolean DEBUG = false; 11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private ItemBridgeAdapter.ViewHolder mSelectedViewHolder; 11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private boolean mExpand = true; 11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private boolean mViewsCreated; 11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private float mRowScaleFactor; 12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private boolean mRowScaleEnabled; 12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private OnItemSelectedListener mOnItemSelectedListener; 12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private OnItemViewSelectedListener mOnItemViewSelectedListener; 12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private OnItemClickedListener mOnItemClickedListener; 12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private OnItemViewClickedListener mOnItemViewClickedListener; 12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Select animation and interpolator are not intended to be 12861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // exposed at this moment. They might be synced with vertical scroll 12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // animation later. 13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int mSelectAnimatorDuration; 13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu Interpolator mSelectAnimatorInterpolator = new DecelerateInterpolator(2); 13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private RecyclerView.RecycledViewPool mRecycledViewPool; 13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private ArrayList<Presenter> mPresenterMapper; 13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private ItemBridgeAdapter.AdapterListener mExternalAdapterListener; 13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item clicked listener on the fragment. 14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * OnItemClickedListener will override {@link View.OnClickListener} that 14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * So in general, developer should choose one of the listeners but not both. 14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @deprecated Use {@link #setOnItemViewClickedListener(OnItemViewClickedListener)} 14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemClickedListener(OnItemClickedListener listener) { 14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mOnItemClickedListener = listener; 14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mViewsCreated) { 14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu throw new IllegalStateException( 14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu "Item clicked listener must be set before views are created"); 15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the item clicked listener. 15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @deprecated Use {@link #getOnItemClickedListener()} 15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public OnItemClickedListener getOnItemClickedListener() { 15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mOnItemClickedListener; 15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 16161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 16261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item clicked listener on the fragment. 16361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * OnItemViewClickedListener will override {@link View.OnClickListener} that 16461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 16561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * So in general, developer should choose one of the listeners but not both. 16661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 16761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 16861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mOnItemViewClickedListener = listener; 16961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mViewsCreated) { 17061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu throw new IllegalStateException( 17161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu "Item clicked listener must be set before views are created"); 17261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 17361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 17461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 17561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 17661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the item clicked listener. 17761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 17861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public OnItemViewClickedListener getOnItemViewClickedListener() { 17961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mOnItemViewClickedListener; 18061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 18161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 18261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 18361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Set the visibility of titles/hovercard of browse rows. 18461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 18561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setExpand(boolean expand) { 18661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExpand = expand; 18761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView listView = getVerticalGridView(); 18861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (listView != null) { 18961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu updateRowScaling(!expand); 19061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final int count = listView.getChildCount(); 19161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "setExpand " + expand + " count " + count); 19261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu for (int i = 0; i < count; i++) { 19361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu View view = listView.getChildAt(i); 19461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) listView.getChildViewHolder(view); 19561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewExpanded(vh, mExpand); 19661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 19761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 19861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 19961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 20061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 20161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item selection listener. 20261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @deprecated Use {@link #setOnItemViewSelectedListener(OnItemViewSelectedListener)} 20361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 20461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemSelectedListener(OnItemSelectedListener listener) { 20561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mOnItemSelectedListener = listener; 20661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView listView = getVerticalGridView(); 20761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (listView != null) { 20861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final int count = listView.getChildCount(); 20961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu for (int i = 0; i < count; i++) { 21061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu View view = listView.getChildAt(i); 21161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) 21261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu listView.getChildViewHolder(view); 21361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setOnItemSelectedListener(vh, mOnItemSelectedListener); 21461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 21561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 21661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 21761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 21861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 21961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item selection listener. 22061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 22161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 22261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mOnItemViewSelectedListener = listener; 22361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView listView = getVerticalGridView(); 22461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (listView != null) { 22561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final int count = listView.getChildCount(); 22661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu for (int i = 0; i < count; i++) { 22761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu View view = listView.getChildAt(i); 22861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) 22961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu listView.getChildViewHolder(view); 23061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setOnItemViewSelectedListener(vh, mOnItemViewSelectedListener); 23161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 23261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 23361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 23461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 23561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 23661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns an item selection listener. 23761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 23861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public OnItemViewSelectedListener getOnItemViewSelectedListener() { 23961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mOnItemViewSelectedListener; 24061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 24161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 24261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 24361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Enables scaling of rows. 24461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 24561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param enable true to enable row scaling 24661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 24761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void enableRowScaling(boolean enable) { 24861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowScaleEnabled = enable; 24961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 25061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 25161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 25261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu protected void onRowSelected(ViewGroup parent, View view, int position, long id) { 25361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView listView = getVerticalGridView(); 25461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (listView == null) { 25561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 25661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 25761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter.ViewHolder vh = (view == null) ? null : 25861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu (ItemBridgeAdapter.ViewHolder) listView.getChildViewHolder(view); 25961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 26061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectedViewHolder != vh) { 26161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "new row selected position " + position + " view " + view); 26261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 26361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectedViewHolder != null) { 26461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewSelected(mSelectedViewHolder, false, false); 26561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 26661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectedViewHolder = vh; 26761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectedViewHolder != null) { 26861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewSelected(mSelectedViewHolder, true, false); 26961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 27061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 27161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 27261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 27361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 27461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu protected int getLayoutResourceId() { 27561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return R.layout.lb_rows_fragment; 27661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 27761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 27861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 27961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onCreate(Bundle savedInstanceState) { 28061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onCreate(savedInstanceState); 28161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectAnimatorDuration = getResources().getInteger( 28261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu R.integer.lb_browse_rows_anim_duration); 28361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRowScaleFactor = getResources().getFraction( 28461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu R.fraction.lb_browse_rows_scale, 1, 1); 28561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 28661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 28761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 28861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onViewCreated(View view, Bundle savedInstanceState) { 28961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "onViewCreated"); 29061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onViewCreated(view, savedInstanceState); 29161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Align the top edge of child with id row_content. 29261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Need set this for directly using RowsSupportFragment. 29361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getVerticalGridView().setItemAlignmentViewId(R.id.row_content); 29461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getVerticalGridView().setSaveChildrenPolicy(VerticalGridView.SAVE_LIMITED_CHILD); 29561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 29661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRecycledViewPool = null; 29761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mPresenterMapper = null; 29861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 29961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 30061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 30161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void setItemAlignment() { 30261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.setItemAlignment(); 30361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (getVerticalGridView() != null) { 30461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getVerticalGridView().setItemAlignmentOffsetWithPadding(true); 30561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 30661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 30761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 30861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void setExternalAdapterListener(ItemBridgeAdapter.AdapterListener listener) { 30961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener = listener; 31061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 31161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 31261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static void setRowViewExpanded(ItemBridgeAdapter.ViewHolder vh, boolean expanded) { 31361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) vh.getPresenter()).setRowViewExpanded(vh.getViewHolder(), expanded); 31461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 31561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 31661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static void setRowViewSelected(ItemBridgeAdapter.ViewHolder vh, boolean selected, 31761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu boolean immediate) { 31861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowViewHolderExtra extra = (RowViewHolderExtra) vh.getExtraObject(); 31961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu extra.animateSelect(selected, immediate); 32061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) vh.getPresenter()).setRowViewSelected(vh.getViewHolder(), selected); 32161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 32261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 32361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static void setOnItemSelectedListener(ItemBridgeAdapter.ViewHolder vh, 32461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu OnItemSelectedListener listener) { 32561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) vh.getPresenter()).setOnItemSelectedListener(listener); 32661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 32761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 32861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static void setOnItemViewSelectedListener(ItemBridgeAdapter.ViewHolder vh, 32961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu OnItemViewSelectedListener listener) { 33061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) vh.getPresenter()).setOnItemViewSelectedListener(listener); 33161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 33261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 33361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private final ItemBridgeAdapter.AdapterListener mBridgeAdapterListener = 33461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu new ItemBridgeAdapter.AdapterListener() { 33561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 33661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onAddPresenter(Presenter presenter, int type) { 33761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) presenter).setOnItemClickedListener(mOnItemClickedListener); 33861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((RowPresenter) presenter).setOnItemViewClickedListener(mOnItemViewClickedListener); 33961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 34061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onAddPresenter(presenter, type); 34161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 34261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 34361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 34461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onCreate(ItemBridgeAdapter.ViewHolder vh) { 34561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView listView = getVerticalGridView(); 34661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (listView != null && ((RowPresenter) vh.getPresenter()).canDrawOutOfBounds()) { 34761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu listView.setClipChildren(false); 34861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 34961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setupSharedViewPool(vh); 35061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mViewsCreated = true; 35161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu vh.setExtraObject(new RowViewHolderExtra(vh)); 35261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // selected state is initialized to false, then driven by grid view onChildSelected 35361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // events. When there is rebind, grid view fires onChildSelected event properly. 35461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // So we don't need do anything special later in onBind or onAttachedToWindow. 35561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewSelected(vh, false, true); 35661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 35761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onCreate(vh); 35861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 35961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 36061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 36161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) { 36261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "onAttachToWindow"); 36361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // All views share the same mExpand value. When we attach a view to grid view, 36461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // we should make sure it pick up the latest mExpand value we set early on other 36561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // attached views. For no-structure-change update, the view is rebound to new data, 36661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // but again it should use the unchanged mExpand value, so we don't need do any 36761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // thing in onBind. 36861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewExpanded(vh, mExpand); 36961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setOnItemSelectedListener(vh, mOnItemSelectedListener); 37061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setOnItemViewSelectedListener(vh, mOnItemViewSelectedListener); 37161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 37261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onAttachedToWindow(vh); 37361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 37461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 37561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 37661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) { 37761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mSelectedViewHolder == vh) { 37861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setRowViewSelected(mSelectedViewHolder, false, true); 37961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectedViewHolder = null; 38061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 38161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 38261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onDetachedFromWindow(vh); 38361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 38461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 38561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 38661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onBind(ItemBridgeAdapter.ViewHolder vh) { 38761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 38861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onBind(vh); 38961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 39061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 39161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 39261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onUnbind(ItemBridgeAdapter.ViewHolder vh) { 39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowViewHolderExtra extra = (RowViewHolderExtra) vh.getExtraObject(); 39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu extra.endAnimations(); 39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalAdapterListener != null) { 39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalAdapterListener.onUnbind(vh); 39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private void setupSharedViewPool(ItemBridgeAdapter.ViewHolder bridgeVh) { 40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowPresenter rowPresenter = (RowPresenter) bridgeVh.getPresenter(); 40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowPresenter.ViewHolder rowVh = rowPresenter.getRowViewHolder(bridgeVh.getViewHolder()); 40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (rowVh instanceof ListRowPresenter.ViewHolder) { 40661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu HorizontalGridView view = ((ListRowPresenter.ViewHolder) rowVh).getGridView(); 40761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Recycled view pool is shared between all list rows 40861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mRecycledViewPool == null) { 40961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mRecycledViewPool = view.getRecycledViewPool(); 41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 41161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu view.setRecycledViewPool(mRecycledViewPool); 41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter bridgeAdapter = 41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((ListRowPresenter.ViewHolder) rowVh).getBridgeAdapter(); 41661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mPresenterMapper == null) { 41761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mPresenterMapper = bridgeAdapter.getPresenterMapper(); 41861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu bridgeAdapter.setPresenterMapper(mPresenterMapper); 42061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 42561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu protected void updateAdapter() { 42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.updateAdapter(); 42761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mSelectedViewHolder = null; 42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mViewsCreated = false; 42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 43061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter adapter = getBridgeAdapter(); 43161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (adapter != null) { 43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu adapter.setAdapterListener(mBridgeAdapterListener); 43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 43461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void onTransitionStart() { 43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onTransitionStart(); 43961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu freezeRows(true); 44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu class ExpandPreLayout implements ViewTreeObserver.OnPreDrawListener { 44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final View mVerticalView; 44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final Runnable mCallback; 44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int mState; 44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final static int STATE_INIT = 0; 44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final static int STATE_FIRST_DRAW = 1; 45061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final static int STATE_SECOND_DRAW = 2; 45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ExpandPreLayout(Runnable callback) { 45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mVerticalView = getVerticalGridView(); 45461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mCallback = callback; 45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void execute() { 45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mVerticalView.getViewTreeObserver().addOnPreDrawListener(this); 45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setExpand(false); 46061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mState = STATE_INIT; 46161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 46261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 46461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public boolean onPreDraw() { 46561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mState == STATE_INIT) { 46661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setExpand(true); 46761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mState = STATE_FIRST_DRAW; 46861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else if (mState == STATE_FIRST_DRAW) { 46961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mCallback.run(); 47061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mVerticalView.getViewTreeObserver().removeOnPreDrawListener(this); 47161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mState = STATE_SECOND_DRAW; 47261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 47361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return false; 47461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 47561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 47661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 47761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void onExpandTransitionStart(boolean expand, final Runnable callback) { 47861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu onTransitionStart(); 47961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (expand) { 48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu callback.run(); 48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Run a "pre" layout when we go non-expand, in order to get the initial 48461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // positions of added rows. 48561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu new ExpandPreLayout(callback).execute(); 48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 48761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private void updateRowScaling(boolean scale) { 48961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView view = getVerticalGridView(); 49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ((ViewGroup) view.getParent()).setClipChildren(!mRowScaleEnabled && scale); 49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu view.setPrimaryOverReach((mRowScaleEnabled && scale) ? 1f / mRowScaleFactor : 1f); 49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final float scaleFactor = (mRowScaleEnabled && scale) ? mRowScaleFactor : 1f; 49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu view.setScaleX(scaleFactor); 49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu view.setScaleY(scaleFactor); 49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void onTransitionEnd() { 50061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onTransitionEnd(); 50161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu freezeRows(false); 50261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private void freezeRows(boolean freeze) { 50561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu VerticalGridView verticalView = getVerticalGridView(); 50661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (verticalView != null) { 50761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final int count = verticalView.getChildCount(); 50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu for (int i = 0; i < count; i++) { 50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder) 51061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu verticalView.getChildViewHolder(verticalView.getChildAt(i)); 51161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowPresenter rowPresenter = (RowPresenter) ibvh.getPresenter(); 51261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowPresenter.ViewHolder vh = rowPresenter.getRowViewHolder(ibvh.getViewHolder()); 51361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu rowPresenter.freeze(vh, freeze); 51461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 51561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 51661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 51761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu} 518