16193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu/* This file is auto-generated from RowsFragment.java.  DO NOT MODIFY. */
26193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu
361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/*
461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Copyright (C) 2014 The Android Open Source Project
561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * in compliance with the License. You may obtain a copy of the License at
861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
1061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
1161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
1261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
1361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
1461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the License.
1561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
1661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupackage android.support.v17.leanback.app;
1761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport java.util.ArrayList;
1961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
2061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.TimeAnimator;
2161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.TimeAnimator.TimeListener;
2261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Bundle;
2361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R;
2461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ItemBridgeAdapter;
2561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener;
2661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener;
2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter.ViewHolder;
281f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.support.v17.leanback.widget.ScaleFrameLayout;
2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.HorizontalGridView;
3161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemSelectedListener;
3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemClickedListener;
3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter;
3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ListRowPresenter;
3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter;
3661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v7.widget.RecyclerView;
3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log;
381f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.view.LayoutInflater;
3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View;
4061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup;
4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewTreeObserver;
4261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.animation.DecelerateInterpolator;
4361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.animation.Interpolator;
4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/**
4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * An ordered set of rows of leanback widgets.
4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupublic class RowsSupportFragment extends BaseRowSupportFragment {
4961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Internal helper class that manages row select animation and apply a default
5261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * dim to each row.
5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
5461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    final class RowViewHolderExtra implements TimeListener {
5561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final RowPresenter mRowPresenter;
5661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final Presenter.ViewHolder mRowViewHolder;
5761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final TimeAnimator mSelectAnimator = new TimeAnimator();
5961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mSelectAnimatorDurationInUse;
6161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        Interpolator mSelectAnimatorInterpolatorInUse;
6261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        float mSelectLevelAnimStart;
6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        float mSelectLevelAnimDelta;
6461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        RowViewHolderExtra(ItemBridgeAdapter.ViewHolder ibvh) {
6661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowPresenter = (RowPresenter) ibvh.getPresenter();
6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowViewHolder = ibvh.getViewHolder();
6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mSelectAnimator.setTimeListener(this);
6961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
7061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
7261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
7361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mSelectAnimator.isRunning()) {
7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                updateSelect(totalTime, deltaTime);
7561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
7661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void updateSelect(long totalTime, long deltaTime) {
7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            float fraction;
8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (totalTime >= mSelectAnimatorDurationInUse) {
8161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                fraction = 1;
8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectAnimator.end();
8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
8461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                fraction = (float) (totalTime / (double) mSelectAnimatorDurationInUse);
8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mSelectAnimatorInterpolatorInUse != null) {
8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                fraction = mSelectAnimatorInterpolatorInUse.getInterpolation(fraction);
8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            float level =  mSelectLevelAnimStart + fraction * mSelectLevelAnimDelta;
9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowPresenter.setSelectLevel(mRowViewHolder, level);
9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void animateSelect(boolean select, boolean immediate) {
9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            endSelectAnimation();
9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final float end = select ? 1 : 0;
9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (immediate) {
9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRowPresenter.setSelectLevel(mRowViewHolder, end);
9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (mRowPresenter.getSelectLevel(mRowViewHolder) != end) {
9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectAnimatorDurationInUse = mSelectAnimatorDuration;
10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectAnimatorInterpolatorInUse = mSelectAnimatorInterpolator;
10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectLevelAnimStart = mRowPresenter.getSelectLevel(mRowViewHolder);
10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectLevelAnimDelta = end - mSelectLevelAnimStart;
10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectAnimator.start();
10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void endAnimations() {
10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            endSelectAnimation();
10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void endSelectAnimation() {
11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mSelectAnimator.end();
11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String TAG = "RowsSupportFragment";
11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final boolean DEBUG = false;
11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ItemBridgeAdapter.ViewHolder mSelectedViewHolder;
12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mExpand = true;
12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mViewsCreated;
12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private float mRowScaleFactor;
1241f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private int mAlignedTop;
12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mRowScaleEnabled;
1261f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private ScaleFrameLayout mScaleFrameLayout;
1271f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private boolean mInTransition;
1283f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    private boolean mAfterEntranceTransition = true;
12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemSelectedListener mOnItemSelectedListener;
13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mOnItemViewSelectedListener;
13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemClickedListener mOnItemClickedListener;
13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewClickedListener mOnItemViewClickedListener;
13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // Select animation and interpolator are not intended to be
13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // exposed at this moment. They might be synced with vertical scroll
13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // animation later.
13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    int mSelectAnimatorDuration;
13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    Interpolator mSelectAnimatorInterpolator = new DecelerateInterpolator(2);
14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private RecyclerView.RecycledViewPool mRecycledViewPool;
14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ArrayList<Presenter> mPresenterMapper;
14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ItemBridgeAdapter.AdapterListener mExternalAdapterListener;
14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1461f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
1471f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    protected VerticalGridView findGridViewFromRoot(View view) {
1481f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        return (VerticalGridView) view.findViewById(R.id.container_list);
1491f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
1501f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * OnItemClickedListener will override {@link View.OnClickListener} that
15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * So in general,  developer should choose one of the listeners but not both.
15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #setOnItemViewClickedListener(OnItemViewClickedListener)}
15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemClickedListener(OnItemClickedListener listener) {
15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemClickedListener = listener;
16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mViewsCreated) {
16161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException(
16261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    "Item clicked listener must be set before views are created");
16361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
16461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
16561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
16661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
16761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item clicked listener.
16861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #getOnItemClickedListener()}
16961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
17061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemClickedListener getOnItemClickedListener() {
17161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemClickedListener;
17261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
17361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
17561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
17661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * OnItemViewClickedListener will override {@link View.OnClickListener} that
17761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
17861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * So in general,  developer should choose one of the listeners but not both.
17961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
18061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
18161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemViewClickedListener = listener;
18261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mViewsCreated) {
18361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException(
18461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    "Item clicked listener must be set before views are created");
18561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
18661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
18761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
18861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
18961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item clicked listener.
19061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
19161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewClickedListener getOnItemViewClickedListener() {
19261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemViewClickedListener;
19361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
19461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
19561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
19661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Set the visibility of titles/hovercard of browse rows.
19761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
19861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setExpand(boolean expand) {
19961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExpand = expand;
20061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        VerticalGridView listView = getVerticalGridView();
20161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (listView != null) {
2021f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            updateRowScaling();
20361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int count = listView.getChildCount();
20461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "setExpand " + expand + " count " + count);
20561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < count; i++) {
20661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                View view = listView.getChildAt(i);
20761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) listView.getChildViewHolder(view);
20861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setRowViewExpanded(vh, mExpand);
20961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
21061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
21161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
21261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
21361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
21461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener.
21561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #setOnItemViewSelectedListener(OnItemViewSelectedListener)}
21661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
21761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
21861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemSelectedListener = listener;
21961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        VerticalGridView listView = getVerticalGridView();
22061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (listView != null) {
22161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int count = listView.getChildCount();
22261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < count; i++) {
22361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                View view = listView.getChildAt(i);
22461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder)
22561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        listView.getChildViewHolder(view);
22661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setOnItemSelectedListener(vh, mOnItemSelectedListener);
22761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
22861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
22961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
23061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
23161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
23261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener.
23361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
23461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
23561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemViewSelectedListener = listener;
23661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        VerticalGridView listView = getVerticalGridView();
23761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (listView != null) {
23861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int count = listView.getChildCount();
23961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < count; i++) {
24061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                View view = listView.getChildAt(i);
24161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder)
24261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        listView.getChildViewHolder(view);
24361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setOnItemViewSelectedListener(vh, mOnItemViewSelectedListener);
24461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
24561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
24661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
24761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
24861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
24961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns an item selection listener.
25061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
25161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewSelectedListener getOnItemViewSelectedListener() {
25261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemViewSelectedListener;
25361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
25461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
25561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
25661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Enables scaling of rows.
25761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
25861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param enable true to enable row scaling
25961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
26061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void enableRowScaling(boolean enable) {
26161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowScaleEnabled = enable;
26261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
26361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
26461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
26542752c860a26deacca04ea9ebeb00ddb4d8ce2fcDake Gu    void onRowSelected(ViewGroup parent, View view, int position, long id) {
26661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        VerticalGridView listView = getVerticalGridView();
26761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (listView == null) {
26861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
26961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
27061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ItemBridgeAdapter.ViewHolder vh = (view == null) ? null :
27161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            (ItemBridgeAdapter.ViewHolder) listView.getChildViewHolder(view);
27261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
27361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mSelectedViewHolder != vh) {
27461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "new row selected position " + position + " view " + view);
27561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
27661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mSelectedViewHolder != null) {
27761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setRowViewSelected(mSelectedViewHolder, false, false);
27861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
27961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mSelectedViewHolder = vh;
28061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mSelectedViewHolder != null) {
28161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setRowViewSelected(mSelectedViewHolder, true, false);
28261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
28361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
28461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
28561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
28661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
28742752c860a26deacca04ea9ebeb00ddb4d8ce2fcDake Gu    int getLayoutResourceId() {
28861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return R.layout.lb_rows_fragment;
28961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
29061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
29161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
29261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onCreate(Bundle savedInstanceState) {
29361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onCreate(savedInstanceState);
29461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSelectAnimatorDuration = getResources().getInteger(
29561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                R.integer.lb_browse_rows_anim_duration);
29661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowScaleFactor = getResources().getFraction(
29761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                R.fraction.lb_browse_rows_scale, 1, 1);
29861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
29961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
30061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
3011f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
3021f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            Bundle savedInstanceState) {
3031f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        View view = super.onCreateView(inflater, container, savedInstanceState);
3041f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        mScaleFrameLayout = (ScaleFrameLayout) view.findViewById(R.id.scale_frame);
3051f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        return view;
3061f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
3071f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
3081f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
30961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onViewCreated(View view, Bundle savedInstanceState) {
31061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "onViewCreated");
31161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onViewCreated(view, savedInstanceState);
31261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Align the top edge of child with id row_content.
31361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Need set this for directly using RowsSupportFragment.
31461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        getVerticalGridView().setItemAlignmentViewId(R.id.row_content);
31561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        getVerticalGridView().setSaveChildrenPolicy(VerticalGridView.SAVE_LIMITED_CHILD);
31661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
31761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRecycledViewPool = null;
31861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mPresenterMapper = null;
31961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
32061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
32161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
322bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout    public void onDestroyView() {
323bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout        mViewsCreated = false;
324bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout        super.onDestroyView();
325bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout    }
326bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout
327bed2e0359e5c75e29cc41642833021bac9f671f5Craig Stout    @Override
32861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void setItemAlignment() {
32961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.setItemAlignment();
33061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getVerticalGridView() != null) {
33161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getVerticalGridView().setItemAlignmentOffsetWithPadding(true);
33261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
33361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
33461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
33561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void setExternalAdapterListener(ItemBridgeAdapter.AdapterListener listener) {
33661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalAdapterListener = listener;
33761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
33861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
3393595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu    /**
3403595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu     * Get the view that will change scale.
3413595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu     */
3423595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu    View getScaleView() {
3433595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        return getVerticalGridView();
3443595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu    }
3453595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu
3463595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu    /**
3473595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu     * Set pivots to scale rows fragment.
3483595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu     */
3493595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu    void setScalePivots(float pivotX, float pivotY) {
3503595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        // set pivot on ScaleFrameLayout, it will be propagated to its child VerticalGridView
3513595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        // where we actually change scale.
3523595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        mScaleFrameLayout.setPivotX(pivotX);
3533595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        mScaleFrameLayout.setPivotY(pivotY);
3541f97045e486f6680a5e8ddcff383df6988fc1b56Craig Stout    }
3551f97045e486f6680a5e8ddcff383df6988fc1b56Craig Stout
35661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static void setRowViewExpanded(ItemBridgeAdapter.ViewHolder vh, boolean expanded) {
35761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ((RowPresenter) vh.getPresenter()).setRowViewExpanded(vh.getViewHolder(), expanded);
35861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
35961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
36061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static void setRowViewSelected(ItemBridgeAdapter.ViewHolder vh, boolean selected,
36161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            boolean immediate) {
36261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        RowViewHolderExtra extra = (RowViewHolderExtra) vh.getExtraObject();
36361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        extra.animateSelect(selected, immediate);
36461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ((RowPresenter) vh.getPresenter()).setRowViewSelected(vh.getViewHolder(), selected);
36561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
36661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
36761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static void setOnItemSelectedListener(ItemBridgeAdapter.ViewHolder vh,
36861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            OnItemSelectedListener listener) {
36961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ((RowPresenter) vh.getPresenter()).setOnItemSelectedListener(listener);
37061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
37161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static void setOnItemViewSelectedListener(ItemBridgeAdapter.ViewHolder vh,
37361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            OnItemViewSelectedListener listener) {
37461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ((RowPresenter) vh.getPresenter()).setOnItemViewSelectedListener(listener);
37561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
37661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final ItemBridgeAdapter.AdapterListener mBridgeAdapterListener =
37861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new ItemBridgeAdapter.AdapterListener() {
37961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
38061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAddPresenter(Presenter presenter, int type) {
38161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            ((RowPresenter) presenter).setOnItemClickedListener(mOnItemClickedListener);
38261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            ((RowPresenter) presenter).setOnItemViewClickedListener(mOnItemViewClickedListener);
38361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
38461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onAddPresenter(presenter, type);
38561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
38661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
38761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
38861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onCreate(ItemBridgeAdapter.ViewHolder vh) {
38961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            VerticalGridView listView = getVerticalGridView();
390c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            if (listView != null) {
391c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                // set clip children false for slide animation
39261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                listView.setClipChildren(false);
39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setupSharedViewPool(vh);
39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mViewsCreated = true;
39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            vh.setExtraObject(new RowViewHolderExtra(vh));
39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // selected state is initialized to false, then driven by grid view onChildSelected
39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // events.  When there is rebind, grid view fires onChildSelected event properly.
39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // So we don't need do anything special later in onBind or onAttachedToWindow.
40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setRowViewSelected(vh, false, true);
40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onCreate(vh);
40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
40661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) {
40761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onAttachToWindow");
40861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // All views share the same mExpand value.  When we attach a view to grid view,
40961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // we should make sure it pick up the latest mExpand value we set early on other
41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // attached views.  For no-structure-change update,  the view is rebound to new data,
41161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // but again it should use the unchanged mExpand value,  so we don't need do any
41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // thing in onBind.
41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setRowViewExpanded(vh, mExpand);
41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setOnItemSelectedListener(vh, mOnItemSelectedListener);
41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setOnItemViewSelectedListener(vh, mOnItemViewSelectedListener);
416c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            RowPresenter rowPresenter = (RowPresenter) vh.getPresenter();
417c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            RowPresenter.ViewHolder rowVh = rowPresenter.getRowViewHolder(vh.getViewHolder());
4183f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu            rowPresenter.setEntranceTransitionState(rowVh, mAfterEntranceTransition);
41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
42061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onAttachedToWindow(vh);
42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) {
42561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mSelectedViewHolder == vh) {
42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setRowViewSelected(mSelectedViewHolder, false, true);
42761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mSelectedViewHolder = null;
42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
43061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onDetachedFromWindow(vh);
43161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
43461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onBind(ItemBridgeAdapter.ViewHolder vh) {
43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onBind(vh);
43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
43961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onUnbind(ItemBridgeAdapter.ViewHolder vh) {
44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            RowViewHolderExtra extra = (RowViewHolderExtra) vh.getExtraObject();
44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            extra.endAnimations();
44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalAdapterListener != null) {
44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalAdapterListener.onUnbind(vh);
44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void setupSharedViewPool(ItemBridgeAdapter.ViewHolder bridgeVh) {
45061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        RowPresenter rowPresenter = (RowPresenter) bridgeVh.getPresenter();
45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        RowPresenter.ViewHolder rowVh = rowPresenter.getRowViewHolder(bridgeVh.getViewHolder());
45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (rowVh instanceof ListRowPresenter.ViewHolder) {
45461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            HorizontalGridView view = ((ListRowPresenter.ViewHolder) rowVh).getGridView();
45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Recycled view pool is shared between all list rows
45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mRecycledViewPool == null) {
45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRecycledViewPool = view.getRecycledViewPool();
45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                view.setRecycledViewPool(mRecycledViewPool);
46061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
46161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
46261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            ItemBridgeAdapter bridgeAdapter =
46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    ((ListRowPresenter.ViewHolder) rowVh).getBridgeAdapter();
46461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mPresenterMapper == null) {
46561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mPresenterMapper = bridgeAdapter.getPresenterMapper();
46661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
46761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                bridgeAdapter.setPresenterMapper(mPresenterMapper);
46861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
46961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
47061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
47161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
47261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
47342752c860a26deacca04ea9ebeb00ddb4d8ce2fcDake Gu    void updateAdapter() {
47461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.updateAdapter();
47561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSelectedViewHolder = null;
47661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mViewsCreated = false;
47761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
47861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ItemBridgeAdapter adapter = getBridgeAdapter();
47961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (adapter != null) {
48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            adapter.setAdapterListener(mBridgeAdapterListener);
48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
48461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
48561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void onTransitionStart() {
48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onTransitionStart();
4871f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        mInTransition = true;
48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        freezeRows(true);
48961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    class ExpandPreLayout implements ViewTreeObserver.OnPreDrawListener {
49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final View mVerticalView;
49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final Runnable mCallback;
49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mState;
49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final static int STATE_INIT = 0;
49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final static int STATE_FIRST_DRAW = 1;
49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final static int STATE_SECOND_DRAW = 2;
50061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
50161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ExpandPreLayout(Runnable callback) {
50261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mVerticalView = getVerticalGridView();
50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mCallback = callback;
50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
50561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
50661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void execute() {
50761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mVerticalView.getViewTreeObserver().addOnPreDrawListener(this);
50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setExpand(false);
50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mState = STATE_INIT;
51061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
51161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
51261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
51361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onPreDraw() {
51461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mState == STATE_INIT) {
51561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setExpand(true);
51661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mState = STATE_FIRST_DRAW;
51761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (mState == STATE_FIRST_DRAW) {
51861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mCallback.run();
51961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mVerticalView.getViewTreeObserver().removeOnPreDrawListener(this);
52061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mState = STATE_SECOND_DRAW;
52161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
52261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return false;
52361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
52461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void onExpandTransitionStart(boolean expand, final Runnable callback) {
52761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        onTransitionStart();
52861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (expand) {
52961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            callback.run();
53061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
53161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
53261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Run a "pre" layout when we go non-expand, in order to get the initial
53361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // positions of added rows.
53461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        new ExpandPreLayout(callback).execute();
53561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
53661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5371f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private boolean needsScale() {
5381f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        return mRowScaleEnabled && !mExpand;
5391f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
54061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5411f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private void updateRowScaling() {
5421f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        final float scaleFactor = needsScale() ? mRowScaleFactor : 1f;
5431f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        mScaleFrameLayout.setLayoutScaleY(scaleFactor);
5443595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        getScaleView().setScaleY(scaleFactor);
5453595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        getScaleView().setScaleX(scaleFactor);
5461f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        updateWindowAlignOffset();
5471f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
5481f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
5491f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private void updateWindowAlignOffset() {
5501f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        int alignOffset = mAlignedTop;
5511f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (needsScale()) {
5521f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            alignOffset = (int) (alignOffset / mRowScaleFactor + 0.5f);
5531f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
5541f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        getVerticalGridView().setWindowAlignmentOffset(alignOffset);
5551f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
5561f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
5571f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
5581f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    void setWindowAlignmentFromTop(int alignedTop) {
5591f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        mAlignedTop = alignedTop;
5601f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        final VerticalGridView gridView = getVerticalGridView();
5611f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (gridView != null) {
5621f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            updateWindowAlignOffset();
5631f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            // align to a fixed position from top
5641f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            gridView.setWindowAlignmentOffsetPercent(
5651f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
5661f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            gridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
5671f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
56861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
56961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
57161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void onTransitionEnd() {
57261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onTransitionEnd();
5731f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        mInTransition = false;
57461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        freezeRows(false);
57561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
57661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void freezeRows(boolean freeze) {
57861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        VerticalGridView verticalView = getVerticalGridView();
57961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (verticalView != null) {
58061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int count = verticalView.getChildCount();
58161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < count; i++) {
58261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder)
58361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    verticalView.getChildViewHolder(verticalView.getChildAt(i));
58461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                RowPresenter rowPresenter = (RowPresenter) ibvh.getPresenter();
58561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                RowPresenter.ViewHolder vh = rowPresenter.getRowViewHolder(ibvh.getViewHolder());
58661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                rowPresenter.freeze(vh, freeze);
58761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
58861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
58961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
590c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
5913f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    /**
5923f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * For rows that willing to participate entrance transition,  this function
5933f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * hide views if afterTransition is true,  show views if afterTransition is false.
5943f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     */
5953f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    void setEntranceTransitionState(boolean afterTransition) {
5963f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mAfterEntranceTransition = afterTransition;
597c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        VerticalGridView verticalView = getVerticalGridView();
598c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (verticalView != null) {
599c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            final int count = verticalView.getChildCount();
600c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            for (int i = 0; i < count; i++) {
601c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder)
602c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                    verticalView.getChildViewHolder(verticalView.getChildAt(i));
603c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                RowPresenter rowPresenter = (RowPresenter) ibvh.getPresenter();
604c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                RowPresenter.ViewHolder vh = rowPresenter.getRowViewHolder(ibvh.getViewHolder());
6053f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu                rowPresenter.setEntranceTransitionState(vh, mAfterEntranceTransition);
606c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
607c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
608c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
60961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu}
610