165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.dialog.old;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.Animator;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.AnimatorListenerAdapter;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.ObjectAnimator;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.Activity;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.ColorDrawable;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup.LayoutParams;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewTreeObserver;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.DecelerateInterpolator;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.Interpolator;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.ImageView;
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.RelativeLayout;
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.TextView;
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.R;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.UriUtils;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.TransitionImage;
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.TransitionImageAnimation;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.widget.FrameLayoutWithShadows;
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List;
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * This class exists to make extending both v4 DialogFragments and regular DialogFragments easy
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class BaseDialogFragment {
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int ANIMATE_IN_DURATION = 250;
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int ANIMATE_DELAY = 550;
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int SLIDE_IN_STAGGER = 100;
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int SLIDE_IN_DISTANCE = 120;
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String TAG_CONTENT = "content";
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String TAG_ACTION = "action";
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int mContentAreaId = R.id.content_fragment;
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int mActionAreaId = R.id.action_fragment;
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public FrameLayoutWithShadows mShadowLayer;
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean mFirstOnStart = true;
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean mIntroAnimationInProgress = false;
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private LiteFragment mFragment;
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    // Related to activity entry transition
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public ColorDrawable mBgDrawable = new ColorDrawable();
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public BaseDialogFragment(LiteFragment fragment) {
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mFragment = fragment;
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onActionClicked(Activity activity, Action action) {
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (activity instanceof ActionAdapter.Listener) {
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ((ActionAdapter.Listener) activity).onActionClicked(action);
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Intent intent = action.getIntent();
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (intent != null) {
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                activity.startActivity(intent);
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                activity.finish();
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void disableEntryAnimation() {
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mFirstOnStart = false;
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * This method sets the layout property of this class. <br/>
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Activities extending {@link DialogFragment} should call this method
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * before calling {@link #onCreate(Bundle)} if they want to have a
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * custom view.
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param contentAreaId id of the content area
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param actionAreaId id of the action area
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setLayoutProperties(int contentAreaId, int actionAreaId) {
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mContentAreaId = contentAreaId;
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mActionAreaId = actionAreaId;
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void performEntryTransition(final Activity activity, final ViewGroup contentView,
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int iconResourceId, Uri iconResourceUri, final ImageView icon, final TextView title,
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            final TextView description, final TextView breadcrumb) {
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // Pull out the root layout of the dialog and set the background drawable, to be
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // faded in during the transition.
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        final RelativeLayout twoPane = (RelativeLayout) contentView.getChildAt(0);
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        twoPane.setVisibility(View.INVISIBLE);
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // If the appropriate data is embedded in the intent and there is an icon specified
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // in the content fragment, we animate the icon from its initial position to the final
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // position. Otherwise, we perform a simpler transition in which the ActionFragment
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // slides in and the ContentFragment text fields slide in.
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mIntroAnimationInProgress = true;
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean lShouldAnimateIcon = true;
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean uriMatch = false;
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        List<TransitionImage> images = TransitionImage.readMultipleFromIntent(
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                activity, activity.getIntent());
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        TransitionImageAnimation ltransitionAnimation = null;
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        final Uri iconUri;
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        final int color;
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (images != null && images.size() > 0) {
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (iconResourceId != 0) {
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                iconUri = Uri.parse(UriUtils.getAndroidResourceUri(
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        activity, iconResourceId));
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (iconResourceUri != null) {
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                iconUri = iconResourceUri;
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                iconUri = null;
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            TransitionImage src = images.get(0);
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            color = src.getBackground();
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (iconUri != null) {
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ltransitionAnimation = new TransitionImageAnimation(contentView);
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ltransitionAnimation.addTransitionSource(src);
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ltransitionAnimation.transitionDurationMs(ANIMATE_IN_DURATION)
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .transitionStartDelayMs(0)
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .interpolator(new DecelerateInterpolator(1f));
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            iconUri = null;
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            color = 0;
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        final TransitionImageAnimation transitionAnimation = ltransitionAnimation;
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // Fade out the old activity, and hard cut the new activity.
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        activity.overridePendingTransition(R.anim.hard_cut_in, R.anim.fade_out);
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int bgColor = mFragment.getResources().getColor(R.color.dialog_activity_background);
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBgDrawable.setColor(bgColor);
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBgDrawable.setAlpha(0);
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        twoPane.setBackground(mBgDrawable);
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // If we're animating the icon, we create a new ImageView in which to place the embedded
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // bitmap. We place it in the root layout to match its location in the previous activity.
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mShadowLayer = (FrameLayoutWithShadows) twoPane.findViewById(R.id.shadow_layout);
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (transitionAnimation != null) {
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            transitionAnimation.listener(new TransitionImageAnimation.Listener() {
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                @Override
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                public void onRemovedView(TransitionImage src, TransitionImage dst) {
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (icon != null) {
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        //want to make sure that users still see at least the source image
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        // if the dst image is too large to finish downloading before the
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        // animation is done. Check if the icon is not visible. This mean
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        // BaseContentFragement have not finish downloading the image yet.
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (icon.getVisibility() != View.VISIBLE) {
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            icon.setImageDrawable(src.getBitmap());
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            int intrinsicWidth = icon.getDrawable().getIntrinsicWidth();
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            LayoutParams lp = icon.getLayoutParams();
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            lp.height = lp.width * icon.getDrawable().getIntrinsicHeight()
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                    / intrinsicWidth;
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            icon.setVisibility(View.VISIBLE);
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        icon.setAlpha(1f);
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (mShadowLayer != null) {
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        mShadowLayer.setShadowsAlpha(1f);
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    onIntroAnimationFinished();
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            });
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            icon.setAlpha(0f);
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (mShadowLayer != null) {
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mShadowLayer.setShadowsAlpha(0f);
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // We need to defer the remainder of the animation preparation until the first
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // layout has occurred, as we don't yet know the final location of the icon.
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        twoPane.getViewTreeObserver().addOnGlobalLayoutListener(
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                new ViewTreeObserver.OnGlobalLayoutListener() {
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            @Override
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            public void onGlobalLayout() {
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                twoPane.getViewTreeObserver().removeOnGlobalLayoutListener(this);
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // if we buildLayer() at this time,  the texture is actually not created
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // delay a little so we can make sure all hardware layer is created before
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // animation, in that way we can avoid the jittering of start animation
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                twoPane.postOnAnimationDelayed(mEntryAnimationRunnable, ANIMATE_DELAY);
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Runnable mEntryAnimationRunnable = new Runnable() {
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                @Override
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                public void run() {
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (!mFragment.isAdded()) {
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        // We have been detached before this could run, so just bail
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        return;
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    twoPane.setVisibility(View.VISIBLE);
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    final int secondaryDelay = SLIDE_IN_DISTANCE;
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    // Fade in the activity background protection
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    ObjectAnimator oa = ObjectAnimator.ofInt(mBgDrawable, "alpha", 255);
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    oa.setDuration(ANIMATE_IN_DURATION);
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    oa.setStartDelay(secondaryDelay);
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    oa.setInterpolator(new DecelerateInterpolator(1.0f));
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    oa.start();
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    // Fade in and slide in the ContentFragment TextViews from the left.
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    prepareAndAnimateView(title, 0, - SLIDE_IN_DISTANCE,
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            secondaryDelay, ANIMATE_IN_DURATION,
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            new DecelerateInterpolator(1.0f),
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            false);
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    prepareAndAnimateView(breadcrumb, 0, - SLIDE_IN_DISTANCE,
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            secondaryDelay, ANIMATE_IN_DURATION,
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            new DecelerateInterpolator(1.0f),
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            false);
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    prepareAndAnimateView(description, 0,
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            - SLIDE_IN_DISTANCE,
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            secondaryDelay, ANIMATE_IN_DURATION,
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            new DecelerateInterpolator(1.0f),
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            false);
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    // Fade in and slide in the ActionFragment from the right.
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    View actionFragmentView = activity.findViewById(mActionAreaId);
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    prepareAndAnimateView(actionFragmentView, 0,
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            actionFragmentView.getMeasuredWidth(), secondaryDelay,
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            ANIMATE_IN_DURATION, new DecelerateInterpolator(1.0f),
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            false);
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (icon != null && transitionAnimation != null) {
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        // now we get the icon view in place,  update the transition target
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        TransitionImage target = new TransitionImage();
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        target.setUri(iconUri);
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        target.createFromImageView(icon);
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (icon.getBackground() instanceof ColorDrawable) {
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            ColorDrawable d = (ColorDrawable) icon.getBackground();
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            target.setBackground(d.getColor());
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        transitionAnimation.addTransitionTarget(target);
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        transitionAnimation.startTransition();
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    } else if (icon != null) {
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        prepareAndAnimateView(icon, 0, - SLIDE_IN_DISTANCE,
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                secondaryDelay, ANIMATE_IN_DURATION,
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                new DecelerateInterpolator(1.0f), true /* is the icon */);
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (mShadowLayer != null) {
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            mShadowLayer.setShadowsAlpha(0f);
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            };
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        });
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Animates a view.
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param v              view to animate
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param initAlpha      initial alpha
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param initTransX     initial translation in the X
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param delay          delay in ms
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param duration       duration in ms
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param interpolator   interpolator to be used, can be null
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param isIcon         if {@code true}, this is the main icon being moved
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void prepareAndAnimateView(final View v, float initAlpha, float initTransX, int delay,
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int duration, Interpolator interpolator, final boolean isIcon) {
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (v != null && v.getWindowToken() != null) {
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.buildLayer();
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.setAlpha(initAlpha);
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.setTranslationX(initTransX);
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.animate().alpha(1f).translationX(0).setDuration(duration).setStartDelay(delay);
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (interpolator != null) {
28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                v.animate().setInterpolator(interpolator);
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.animate().setListener(new AnimatorListenerAdapter() {
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                @Override
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                public void onAnimationEnd(Animator animation) {
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    v.setLayerType(View.LAYER_TYPE_NONE, null);
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (isIcon) {
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (mShadowLayer != null) {
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            mShadowLayer.setShadowsAlpha(1f);
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        onIntroAnimationFinished();
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            });
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            v.animate().start();
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Called when intro animation is finished.
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If a subclass is going to alter the view, should wait until this is called.
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onIntroAnimationFinished() {
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mIntroAnimationInProgress = false;
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean isIntroAnimationInProgress() {
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mIntroAnimationInProgress;
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public ColorDrawable getBackgroundDrawable() {
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mBgDrawable;
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setBackgroundDrawable(ColorDrawable drawable) {
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBgDrawable = drawable;
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
325