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