14121f22713bbed467a977ec0d867ef53989ff374Dake Gu/*
24121f22713bbed467a977ec0d867ef53989ff374Dake Gu * Copyright (C) 2014 The Android Open Source Project
34121f22713bbed467a977ec0d867ef53989ff374Dake Gu *
44121f22713bbed467a977ec0d867ef53989ff374Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
54121f22713bbed467a977ec0d867ef53989ff374Dake Gu * in compliance with the License. You may obtain a copy of the License at
64121f22713bbed467a977ec0d867ef53989ff374Dake Gu *
74121f22713bbed467a977ec0d867ef53989ff374Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
84121f22713bbed467a977ec0d867ef53989ff374Dake Gu *
94121f22713bbed467a977ec0d867ef53989ff374Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
104121f22713bbed467a977ec0d867ef53989ff374Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
114121f22713bbed467a977ec0d867ef53989ff374Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
124121f22713bbed467a977ec0d867ef53989ff374Dake Gu * the License.
134121f22713bbed467a977ec0d867ef53989ff374Dake Gu */
14ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.widget;
154121f22713bbed467a977ec0d867ef53989ff374Dake Gu
163103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.app.Activity;
173103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.graphics.Matrix;
18d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Guimport android.os.Handler;
194121f22713bbed467a977ec0d867ef53989ff374Dake Guimport android.text.TextUtils;
20b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.util.Log;
214121f22713bbed467a977ec0d867ef53989ff374Dake Guimport android.view.View;
224121f22713bbed467a977ec0d867ef53989ff374Dake Guimport android.view.View.MeasureSpec;
233103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.view.ViewGroup;
24b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.widget.ImageView;
25b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.widget.ImageView.ScaleType;
264121f22713bbed467a977ec0d867ef53989ff374Dake Gu
278619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.core.app.ActivityCompat;
288619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.core.app.SharedElementCallback;
298619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.core.view.ViewCompat;
308619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.transition.TransitionHelper;
318619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.transition.TransitionListener;
328619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.widget.DetailsOverviewRowPresenter.ViewHolder;
338619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
342056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Guimport java.lang.ref.WeakReference;
354121f22713bbed467a977ec0d867ef53989ff374Dake Guimport java.util.List;
364121f22713bbed467a977ec0d867ef53989ff374Dake Gu
379306f07b1d66f4974a81f781d29739b30124fff0George Mountfinal class DetailsOverviewSharedElementHelper extends SharedElementCallback {
384121f22713bbed467a977ec0d867ef53989ff374Dake Gu
392056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu    static final String TAG = "DetailsTransitionHelper";
4099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static final boolean DEBUG = false;
41b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
422056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu    static class TransitionTimeOutRunnable implements Runnable {
432056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        WeakReference<DetailsOverviewSharedElementHelper> mHelperRef;
442056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu
452056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        TransitionTimeOutRunnable(DetailsOverviewSharedElementHelper helper) {
462056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            mHelperRef = new WeakReference<DetailsOverviewSharedElementHelper>(helper);
472056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        }
482056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu
492056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        @Override
502056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        public void run() {
512056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            DetailsOverviewSharedElementHelper helper = mHelperRef.get();
522056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            if (helper == null) {
532056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu                return;
542056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            }
552056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            if (DEBUG) {
562056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu                Log.d(TAG, "timeout " + helper.mActivityToRunTransition);
572056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            }
582056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            helper.startPostponedEnterTransition();
592056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu        }
602056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu    }
612056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu
6299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    ViewHolder mViewHolder;
6399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    Activity mActivityToRunTransition;
6499ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    boolean mStartedPostpone;
6599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    String mSharedElementName;
6699ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    int mRightPanelWidth;
6799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    int mRightPanelHeight;
684121f22713bbed467a977ec0d867ef53989ff374Dake Gu
69b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private ScaleType mSavedScaleType;
70b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private Matrix mSavedMatrix;
71b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
72b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private boolean hasImageViewScaleChange(View snapshotView) {
73b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        return snapshotView instanceof ImageView;
74b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
75b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
76b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private void saveImageViewScale() {
77b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (mSavedScaleType == null) {
78b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            // only save first time after initialize/restoreImageViewScale()
79b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            ImageView imageView = mViewHolder.mImageView;
80b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            mSavedScaleType = imageView.getScaleType();
81b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            mSavedMatrix = mSavedScaleType == ScaleType.MATRIX ? imageView.getMatrix() : null;
82b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (DEBUG) {
83b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                Log.d(TAG, "saveImageViewScale: "+mSavedScaleType);
84b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
85b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
86b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
87b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
88b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static void updateImageViewAfterScaleTypeChange(ImageView imageView) {
89b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        // enforcing imageView to update its internal bounds/matrix immediately
90b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        imageView.measure(
91b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                MeasureSpec.makeMeasureSpec(imageView.getMeasuredWidth(), MeasureSpec.EXACTLY),
92b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                MeasureSpec.makeMeasureSpec(imageView.getMeasuredHeight(), MeasureSpec.EXACTLY));
93b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        imageView.layout(imageView.getLeft(), imageView.getTop(),
94b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                imageView.getRight(), imageView.getBottom());
95b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
96b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
97b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private void changeImageViewScale(View snapshotView) {
98b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        ImageView snapshotImageView = (ImageView) snapshotView;
99b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        ImageView imageView = mViewHolder.mImageView;
100b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (DEBUG) {
101b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            Log.d(TAG, "changeImageViewScale to "+snapshotImageView.getScaleType());
102b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
103b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        imageView.setScaleType(snapshotImageView.getScaleType());
104b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (snapshotImageView.getScaleType() == ScaleType.MATRIX) {
105b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            imageView.setImageMatrix(snapshotImageView.getImageMatrix());
106b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
107b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        updateImageViewAfterScaleTypeChange(imageView);
108b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
109b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
110b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private void restoreImageViewScale() {
111b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (mSavedScaleType != null) {
112b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (DEBUG) {
113b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                Log.d(TAG, "restoreImageViewScale to "+mSavedScaleType);
114b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
115b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            ImageView imageView = mViewHolder.mImageView;
116b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            imageView.setScaleType(mSavedScaleType);
117b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (mSavedScaleType == ScaleType.MATRIX) {
118b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                imageView.setImageMatrix(mSavedMatrix);
119b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
120b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            // only restore once unless another save happens
121b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            mSavedScaleType = null;
122b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            updateImageViewAfterScaleTypeChange(imageView);
123b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
124b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
125b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
1264121f22713bbed467a977ec0d867ef53989ff374Dake Gu    @Override
1279306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onSharedElementStart(List<String> sharedElementNames,
1284121f22713bbed467a977ec0d867ef53989ff374Dake Gu            List<View> sharedElements, List<View> sharedElementSnapshots) {
12999881f0d15df96179f93eee2d624b338d327571cDake Gu        if (DEBUG) {
13099881f0d15df96179f93eee2d624b338d327571cDake Gu            Log.d(TAG, "onSharedElementStart " + mActivityToRunTransition);
13199881f0d15df96179f93eee2d624b338d327571cDake Gu        }
1324121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (sharedElements.size() < 1) {
1334121f22713bbed467a977ec0d867ef53989ff374Dake Gu            return;
1344121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
1354121f22713bbed467a977ec0d867ef53989ff374Dake Gu        View overviewView = sharedElements.get(0);
136e7b29b745f6562b43ad79074cf5445a26cd4073cDake Gu        if (mViewHolder == null || mViewHolder.mOverviewFrame != overviewView) {
1374121f22713bbed467a977ec0d867ef53989ff374Dake Gu            return;
1384121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
139b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        View snapshot = sharedElementSnapshots.get(0);
140b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (hasImageViewScaleChange(snapshot)) {
141b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            saveImageViewScale();
142b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            changeImageViewScale(snapshot);
143b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
1444121f22713bbed467a977ec0d867ef53989ff374Dake Gu        View imageView = mViewHolder.mImageView;
1454121f22713bbed467a977ec0d867ef53989ff374Dake Gu        final int width = overviewView.getWidth();
1464121f22713bbed467a977ec0d867ef53989ff374Dake Gu        final int height = overviewView.getHeight();
1474121f22713bbed467a977ec0d867ef53989ff374Dake Gu        imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
1484121f22713bbed467a977ec0d867ef53989ff374Dake Gu                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
1494121f22713bbed467a977ec0d867ef53989ff374Dake Gu        imageView.layout(0, 0, width, height);
150b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu        final View rightPanel = mViewHolder.mRightPanel;
1514121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (mRightPanelWidth != 0 && mRightPanelHeight != 0) {
1524121f22713bbed467a977ec0d867ef53989ff374Dake Gu            rightPanel.measure(MeasureSpec.makeMeasureSpec(mRightPanelWidth, MeasureSpec.EXACTLY),
1534121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    MeasureSpec.makeMeasureSpec(mRightPanelHeight, MeasureSpec.EXACTLY));
1544121f22713bbed467a977ec0d867ef53989ff374Dake Gu            rightPanel.layout(width, rightPanel.getTop(), width + mRightPanelWidth,
1554121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    rightPanel.getTop() + mRightPanelHeight);
1564121f22713bbed467a977ec0d867ef53989ff374Dake Gu        } else {
1574121f22713bbed467a977ec0d867ef53989ff374Dake Gu            rightPanel.offsetLeftAndRight(width - rightPanel.getLeft());
1584121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
15972a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu        mViewHolder.mActionsRow.setVisibility(View.INVISIBLE);
16072a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu        mViewHolder.mDetailsDescriptionFrame.setVisibility(View.INVISIBLE);
161b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu    }
162b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu
163b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu    @Override
1649306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onSharedElementEnd(List<String> sharedElementNames,
165b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu            List<View> sharedElements, List<View> sharedElementSnapshots) {
16699881f0d15df96179f93eee2d624b338d327571cDake Gu        if (DEBUG) {
16799881f0d15df96179f93eee2d624b338d327571cDake Gu            Log.d(TAG, "onSharedElementEnd " + mActivityToRunTransition);
16899881f0d15df96179f93eee2d624b338d327571cDake Gu        }
169b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu        if (sharedElements.size() < 1) {
170b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu            return;
171b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu        }
172b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu        View overviewView = sharedElements.get(0);
173e7b29b745f6562b43ad79074cf5445a26cd4073cDake Gu        if (mViewHolder == null || mViewHolder.mOverviewFrame != overviewView) {
174b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu            return;
175b0181a77ce38f75a7d218745a330c5d80daacfb6Dake Gu        }
176b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        restoreImageViewScale();
17795400e6d31a1ac09e48cb8944a79b7250484aa4cDake Gu        // temporary let action row take focus so we defer button background animation
17895400e6d31a1ac09e48cb8944a79b7250484aa4cDake Gu        mViewHolder.mActionsRow.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
17972a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu        mViewHolder.mActionsRow.setVisibility(View.VISIBLE);
18095400e6d31a1ac09e48cb8944a79b7250484aa4cDake Gu        mViewHolder.mActionsRow.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
1819621fcb393357c42b15952a91c80350a798d99f4Dake Gu        // switch focusability to VISIBLE wont trigger focusableViewAvailable() on O because
1829621fcb393357c42b15952a91c80350a798d99f4Dake Gu        // shared element details_frame is still INVISIBLE. b/63544781
1839621fcb393357c42b15952a91c80350a798d99f4Dake Gu        mViewHolder.mActionsRow.requestFocus();
18472a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu        mViewHolder.mDetailsDescriptionFrame.setVisibility(View.VISIBLE);
1854121f22713bbed467a977ec0d867ef53989ff374Dake Gu    }
1864121f22713bbed467a977ec0d867ef53989ff374Dake Gu
187d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    void setSharedElementEnterTransition(Activity activity, String sharedElementName,
188d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu            long timeoutMs) {
189694edde99dc3782374977dab6d9aa34a16c13337Dake Gu        if ((activity == null && !TextUtils.isEmpty(sharedElementName))
190694edde99dc3782374977dab6d9aa34a16c13337Dake Gu                || (activity != null && TextUtils.isEmpty(sharedElementName))) {
1914121f22713bbed467a977ec0d867ef53989ff374Dake Gu            throw new IllegalArgumentException();
1924121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
1933103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        if (activity == mActivityToRunTransition
1943103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                && TextUtils.equals(sharedElementName, mSharedElementName)) {
1954121f22713bbed467a977ec0d867ef53989ff374Dake Gu            return;
1964121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
1974121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (mActivityToRunTransition != null) {
1989306f07b1d66f4974a81f781d29739b30124fff0George Mount            ActivityCompat.setEnterSharedElementCallback(mActivityToRunTransition, null);
1994121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
2004121f22713bbed467a977ec0d867ef53989ff374Dake Gu        mActivityToRunTransition = activity;
2014121f22713bbed467a977ec0d867ef53989ff374Dake Gu        mSharedElementName = sharedElementName;
20299881f0d15df96179f93eee2d624b338d327571cDake Gu        if (DEBUG) {
20399881f0d15df96179f93eee2d624b338d327571cDake Gu            Log.d(TAG, "postponeEnterTransition " + mActivityToRunTransition);
20499881f0d15df96179f93eee2d624b338d327571cDake Gu        }
20599881f0d15df96179f93eee2d624b338d327571cDake Gu        ActivityCompat.setEnterSharedElementCallback(mActivityToRunTransition, this);
20699881f0d15df96179f93eee2d624b338d327571cDake Gu        ActivityCompat.postponeEnterTransition(mActivityToRunTransition);
20799881f0d15df96179f93eee2d624b338d327571cDake Gu        if (timeoutMs > 0) {
2082056c3e52465864d60f6f64c16a0a27629ba5fd8Dake Gu            new Handler().postDelayed(new TransitionTimeOutRunnable(this), timeoutMs);
2094121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
2104121f22713bbed467a977ec0d867ef53989ff374Dake Gu    }
2114121f22713bbed467a977ec0d867ef53989ff374Dake Gu
2124121f22713bbed467a977ec0d867ef53989ff374Dake Gu    void onBindToDrawable(ViewHolder vh) {
21399881f0d15df96179f93eee2d624b338d327571cDake Gu        if (DEBUG) {
21499881f0d15df96179f93eee2d624b338d327571cDake Gu            Log.d(TAG, "onBindToDrawable, could start transition of " + mActivityToRunTransition);
21599881f0d15df96179f93eee2d624b338d327571cDake Gu        }
21699881f0d15df96179f93eee2d624b338d327571cDake Gu        if (mViewHolder != null) {
21799881f0d15df96179f93eee2d624b338d327571cDake Gu            if (DEBUG) {
21899881f0d15df96179f93eee2d624b338d327571cDake Gu                Log.d(TAG, "rebind? clear transitionName on current viewHolder "
21999881f0d15df96179f93eee2d624b338d327571cDake Gu                        + mViewHolder.mOverviewFrame);
22099881f0d15df96179f93eee2d624b338d327571cDake Gu            }
22199881f0d15df96179f93eee2d624b338d327571cDake Gu            ViewCompat.setTransitionName(mViewHolder.mOverviewFrame, null);
22299881f0d15df96179f93eee2d624b338d327571cDake Gu        }
2234121f22713bbed467a977ec0d867ef53989ff374Dake Gu        // After we got a image drawable,  we can determine size of right panel.
2244121f22713bbed467a977ec0d867ef53989ff374Dake Gu        // We want right panel to have fixed size so that the right panel don't change size
2254121f22713bbed467a977ec0d867ef53989ff374Dake Gu        // when the overview is layout as a small bounds in transition.
2264121f22713bbed467a977ec0d867ef53989ff374Dake Gu        mViewHolder = vh;
2274121f22713bbed467a977ec0d867ef53989ff374Dake Gu        mViewHolder.mRightPanel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
2284121f22713bbed467a977ec0d867ef53989ff374Dake Gu            @Override
2294121f22713bbed467a977ec0d867ef53989ff374Dake Gu            public void onLayoutChange(View v, int left, int top, int right, int bottom,
2304121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
2314121f22713bbed467a977ec0d867ef53989ff374Dake Gu                mViewHolder.mRightPanel.removeOnLayoutChangeListener(this);
2324121f22713bbed467a977ec0d867ef53989ff374Dake Gu                mRightPanelWidth = mViewHolder.mRightPanel.getWidth();
2334121f22713bbed467a977ec0d867ef53989ff374Dake Gu                mRightPanelHeight = mViewHolder.mRightPanel.getHeight();
23499881f0d15df96179f93eee2d624b338d327571cDake Gu                if (DEBUG) {
23599881f0d15df96179f93eee2d624b338d327571cDake Gu                    Log.d(TAG, "onLayoutChange records size of right panel as "
23699881f0d15df96179f93eee2d624b338d327571cDake Gu                            + mRightPanelWidth + ", "+ mRightPanelHeight);
23799881f0d15df96179f93eee2d624b338d327571cDake Gu                }
2384121f22713bbed467a977ec0d867ef53989ff374Dake Gu            }
2394121f22713bbed467a977ec0d867ef53989ff374Dake Gu        });
24099881f0d15df96179f93eee2d624b338d327571cDake Gu        mViewHolder.mRightPanel.postOnAnimation(new Runnable() {
24199881f0d15df96179f93eee2d624b338d327571cDake Gu            @Override
24299881f0d15df96179f93eee2d624b338d327571cDake Gu            public void run() {
24399881f0d15df96179f93eee2d624b338d327571cDake Gu                if (DEBUG) {
24499881f0d15df96179f93eee2d624b338d327571cDake Gu                    Log.d(TAG, "setTransitionName "+mViewHolder.mOverviewFrame);
24599881f0d15df96179f93eee2d624b338d327571cDake Gu                }
24699881f0d15df96179f93eee2d624b338d327571cDake Gu                ViewCompat.setTransitionName(mViewHolder.mOverviewFrame, mSharedElementName);
2478403619efebe94666c0615c3fc85080a303acf80Dake Gu                Object transition = TransitionHelper.getSharedElementEnterTransition(
24899881f0d15df96179f93eee2d624b338d327571cDake Gu                        mActivityToRunTransition.getWindow());
24999881f0d15df96179f93eee2d624b338d327571cDake Gu                if (transition != null) {
2508403619efebe94666c0615c3fc85080a303acf80Dake Gu                    TransitionHelper.addTransitionListener(transition, new TransitionListener() {
25199881f0d15df96179f93eee2d624b338d327571cDake Gu                        @Override
25299881f0d15df96179f93eee2d624b338d327571cDake Gu                        public void onTransitionEnd(Object transition) {
25399881f0d15df96179f93eee2d624b338d327571cDake Gu                            if (DEBUG) {
25499881f0d15df96179f93eee2d624b338d327571cDake Gu                                Log.d(TAG, "onTransitionEnd " + mActivityToRunTransition);
255d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu                            }
25699881f0d15df96179f93eee2d624b338d327571cDake Gu                            // after transition if the action row still focused, transfer
25799881f0d15df96179f93eee2d624b338d327571cDake Gu                            // focus to its children
25899881f0d15df96179f93eee2d624b338d327571cDake Gu                            if (mViewHolder.mActionsRow.isFocused()) {
25999881f0d15df96179f93eee2d624b338d327571cDake Gu                                mViewHolder.mActionsRow.requestFocus();
26099881f0d15df96179f93eee2d624b338d327571cDake Gu                            }
2618403619efebe94666c0615c3fc85080a303acf80Dake Gu                            TransitionHelper.removeTransitionListener(transition, this);
26299881f0d15df96179f93eee2d624b338d327571cDake Gu                        }
26399881f0d15df96179f93eee2d624b338d327571cDake Gu                    });
2644121f22713bbed467a977ec0d867ef53989ff374Dake Gu                }
26599881f0d15df96179f93eee2d624b338d327571cDake Gu                startPostponedEnterTransition();
26699881f0d15df96179f93eee2d624b338d327571cDake Gu            }
26799881f0d15df96179f93eee2d624b338d327571cDake Gu        });
26899881f0d15df96179f93eee2d624b338d327571cDake Gu    }
26999881f0d15df96179f93eee2d624b338d327571cDake Gu
27099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void startPostponedEnterTransition() {
27199881f0d15df96179f93eee2d624b338d327571cDake Gu        if (!mStartedPostpone) {
27299881f0d15df96179f93eee2d624b338d327571cDake Gu            if (DEBUG) {
27399881f0d15df96179f93eee2d624b338d327571cDake Gu                Log.d(TAG, "startPostponedEnterTransition " + mActivityToRunTransition);
27499881f0d15df96179f93eee2d624b338d327571cDake Gu            }
27599881f0d15df96179f93eee2d624b338d327571cDake Gu            ActivityCompat.startPostponedEnterTransition(mActivityToRunTransition);
27699881f0d15df96179f93eee2d624b338d327571cDake Gu            mStartedPostpone = true;
2774121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
2784121f22713bbed467a977ec0d867ef53989ff374Dake Gu    }
2794121f22713bbed467a977ec0d867ef53989ff374Dake Gu}
280