DetailsOverviewSharedElementHelper.java revision e7b29b745f6562b43ad79074cf5445a26cd4073c
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.os.Handler;
17import android.support.v4.app.ActivityCompat;
18import android.support.v4.app.SharedElementCallback;
19import android.support.v4.view.ViewCompat;
20import android.support.v17.leanback.R;
21import android.support.v17.leanback.transition.TransitionListener;
22import android.support.v17.leanback.transition.TransitionHelper;
23import android.support.v17.leanback.widget.DetailsOverviewRowPresenter.ViewHolder;
24import android.app.Activity;
25import android.text.TextUtils;
26import android.view.View;
27import android.view.ViewGroup;
28import android.view.View.MeasureSpec;
29
30import java.util.List;
31
32final class DetailsOverviewSharedElementHelper extends SharedElementCallback {
33
34    private ViewHolder mViewHolder;
35    private Activity mActivityToRunTransition;
36    private String mSharedElementName;
37    private int mRightPanelWidth;
38    private int mRightPanelHeight;
39
40    @Override
41    public void onSharedElementStart(List<String> sharedElementNames,
42            List<View> sharedElements, List<View> sharedElementSnapshots) {
43        if (sharedElements.size() < 1) {
44            return;
45        }
46        View overviewView = sharedElements.get(0);
47        if (mViewHolder == null || mViewHolder.mOverviewFrame != overviewView) {
48            return;
49        }
50        View imageView = mViewHolder.mImageView;
51        final int width = overviewView.getWidth();
52        final int height = overviewView.getHeight();
53        imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
54                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
55        imageView.layout(0, 0, width, height);
56        final View rightPanel = mViewHolder.mRightPanel;
57        if (mRightPanelWidth != 0 && mRightPanelHeight != 0) {
58            rightPanel.measure(MeasureSpec.makeMeasureSpec(mRightPanelWidth, MeasureSpec.EXACTLY),
59                    MeasureSpec.makeMeasureSpec(mRightPanelHeight, MeasureSpec.EXACTLY));
60            rightPanel.layout(width, rightPanel.getTop(), width + mRightPanelWidth,
61                    rightPanel.getTop() + mRightPanelHeight);
62        } else {
63            rightPanel.offsetLeftAndRight(width - rightPanel.getLeft());
64        }
65        mViewHolder.mActionsRow.setVisibility(View.INVISIBLE);
66        mViewHolder.mDetailsDescriptionFrame.setVisibility(View.INVISIBLE);
67    }
68
69    @Override
70    public void onSharedElementEnd(List<String> sharedElementNames,
71            List<View> sharedElements, List<View> sharedElementSnapshots) {
72        if (sharedElements.size() < 1) {
73            return;
74        }
75        View overviewView = sharedElements.get(0);
76        if (mViewHolder == null || mViewHolder.mOverviewFrame != overviewView) {
77            return;
78        }
79        // temporary let action row take focus so we defer button background animation
80        mViewHolder.mActionsRow.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
81        mViewHolder.mActionsRow.setVisibility(View.VISIBLE);
82        mViewHolder.mActionsRow.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
83        mViewHolder.mDetailsDescriptionFrame.setVisibility(View.VISIBLE);
84    }
85
86    void setSharedElementEnterTransition(Activity activity, String sharedElementName,
87            long timeoutMs) {
88        if (activity == null && !TextUtils.isEmpty(sharedElementName) ||
89                activity != null && TextUtils.isEmpty(sharedElementName)) {
90            throw new IllegalArgumentException();
91        }
92        if (activity == mActivityToRunTransition &&
93                TextUtils.equals(sharedElementName, mSharedElementName)) {
94            return;
95        }
96        if (mActivityToRunTransition != null) {
97            ActivityCompat.setEnterSharedElementCallback(mActivityToRunTransition, null);
98        }
99        mActivityToRunTransition = activity;
100        mSharedElementName = sharedElementName;
101        if (mActivityToRunTransition != null) {
102            ActivityCompat.setEnterSharedElementCallback(mActivityToRunTransition, this);
103            ActivityCompat.postponeEnterTransition(mActivityToRunTransition);
104            if (timeoutMs > 0) {
105                new Handler().postDelayed(new Runnable() {
106                    @Override
107                    public void run() {
108                        if (mActivityToRunTransition == null) {
109                            return;
110                        }
111                        ActivityCompat.startPostponedEnterTransition(mActivityToRunTransition);
112                        mActivityToRunTransition = null;
113                    }
114                }, timeoutMs);
115            }
116        }
117    }
118
119    void onBindToDrawable(ViewHolder vh) {
120        // After we got a image drawable,  we can determine size of right panel.
121        // We want right panel to have fixed size so that the right panel don't change size
122        // when the overview is layout as a small bounds in transition.
123        mViewHolder = vh;
124        mViewHolder.mRightPanel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
125            @Override
126            public void onLayoutChange(View v, int left, int top, int right, int bottom,
127                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
128                mViewHolder.mRightPanel.removeOnLayoutChangeListener(this);
129                mRightPanelWidth = mViewHolder.mRightPanel.getWidth();
130                mRightPanelHeight = mViewHolder.mRightPanel.getHeight();
131            }
132        });
133        if (mActivityToRunTransition != null) {
134            mViewHolder.mRightPanel.postOnAnimation(new Runnable() {
135                @Override
136                public void run() {
137                    if (mActivityToRunTransition == null) {
138                        return;
139                    }
140                    final TransitionHelper transitionHelper = TransitionHelper.getInstance();
141                    Object transition = transitionHelper.getSharedElementEnterTransition(
142                            mActivityToRunTransition.getWindow());
143                    if (transition != null) {
144                        transitionHelper.setTransitionListener(transition, new TransitionListener() {
145                            @Override
146                            public void onTransitionEnd(Object transition) {
147                                // after transition if the action row still focused, transfer
148                                // focus to its children
149                                if (mViewHolder.mActionsRow.isFocused()) {
150                                    mViewHolder.mActionsRow.requestFocus();
151                                }
152                                transitionHelper.setTransitionListener(transition, null);
153                            }
154                        });
155                    }
156                    ViewCompat.setTransitionName(mViewHolder.mOverviewFrame, mSharedElementName);
157                    ActivityCompat.startPostponedEnterTransition(mActivityToRunTransition);
158                    mActivityToRunTransition = null;
159                    mSharedElementName = null;
160                }
161            });
162        }
163    }
164}
165