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.app.Fragment;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.FragmentManager;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.FragmentManager.OnBackStackChangedListener;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.FragmentTransaction;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Color;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.ColorDrawable;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Build;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
30eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantlerimport android.support.annotation.NonNull;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.LayoutInflater;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View;
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup;
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.Interpolator;
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.R;
3762f1e6e5e7071c9b95911e2ab3120a42e269d53eLeif Hendrik Wildenimport com.android.tv.settings.core.instrumentation.InstrumentedActivity;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * A DialogActivity has 2 fragments, a content fragment and a list fragment.
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p>
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Subclasses should override to supply the content fragment and list items.
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p>
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * The DialogActivity will handle animating in and out.
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p>
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * This class will use a default layout, but a custom layout can be provided by
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * calling {@link #setLayoutProperties}
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
5162f1e6e5e7071c9b95911e2ab3120a42e269d53eLeif Hendrik Wildenpublic abstract class DialogActivity extends InstrumentedActivity
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        implements ActionAdapter.Listener, OnBackStackChangedListener {
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Content Fragment title.
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_TITLE = "dialog_title";
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Content Fragment breadcrumb.
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_BREADCRUMB = "dialog_breadcrumb";
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Content Fragment description.
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_DESCRIPTION = "dialog_description";
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Content Fragment image uri.
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_IMAGE_URI = "dialog_image_uri";
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Content Fragment image background color
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            = "dialog_image_background_color";
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Action Fragment actions starting index.
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_DIALOG_ACTIONS_START_INDEX = "dialog_actions_start_index";
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Dialog Action Fragment actions.
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_PARCELABLE_ACTIONS = "parcelable_actions";
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Whether DialogActivity should create Content Fragment and Action Fragment from extras.
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_CREATE_FRAGMENT_FROM_EXTRA = "create_fragment_from_extra";
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String TAG_DIALOG = "tag_dialog";
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String BACKSTACK_NAME_DIALOG = "backstack_name_dialog";
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String KEY_BACKSTACK_COUNT = "backstack_count";
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected static final int ANIMATE_IN_DURATION = 250;
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private DialogFragment mDialogFragment;
102eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler    private int mLayoutResId = R.layout.lb_dialog_fragment;
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private View mContent;
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mLastBackStackCount = 0;
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public DialogActivity() {
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mDialogFragment = new DialogFragment();
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mDialogFragment.setActivity(this);
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Intent createIntent(Context context, String title,
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String breadcrumb, String description, String imageUri,
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayList<Action> actions) {
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return createIntent(context, title, breadcrumb, description, imageUri,
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Color.TRANSPARENT, actions);
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Intent createIntent(Context context, String title,
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String breadcrumb, String description, String imageUri,
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int imageBackground, ArrayList<Action> actions) {
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = new Intent(context, DialogActivity.class);
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_TITLE, title);
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return intent;
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Intent createIntent(Context context, String title,
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String breadcrumb, String description, String imageUri,
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayList<Action> actions, Class<? extends DialogActivity> activityClass) {
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return createIntent(context, title, breadcrumb, description, imageUri, Color.TRANSPARENT,
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                actions, activityClass);
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Intent createIntent(Context context, String title,
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String breadcrumb, String description, String imageUri, int imageBackground,
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayList<Action> actions, Class<? extends DialogActivity> activityClass) {
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = new Intent(context, activityClass);
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_TITLE, title);
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return intent;
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Intent createIntent(Context context, String title,
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String breadcrumb, String description, String imageUri, int imageBackground,
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayList<Action> actions, Class<? extends DialogActivity> activityClass,
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int startIndex) {
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = new Intent(context, activityClass);
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_TITLE, title);
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_DIALOG_ACTIONS_START_INDEX, startIndex);
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return intent;
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public View getContentView() {
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mContent;
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onCreate(Bundle savedInstanceState) {
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // TODO: replace these hardcoded values with the commented constants whenever Hangouts
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // updates their manifest to build against JB MR2.
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (Build.VERSION.SDK_INT >= 18 /* Build.VERSION_CODES.JELLY_BEAN_MR2 */) {
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            getWindow().addFlags(0x02000000
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    /* WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN */);
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if(savedInstanceState != null) {
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mLastBackStackCount = savedInstanceState.getInt(KEY_BACKSTACK_COUNT);
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onCreate(savedInstanceState);
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getFragmentManager().addOnBackStackChangedListener(this);
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        LayoutInflater helium = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mContent = helium.inflate(mLayoutResId, null);
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setContentView(mContent);
191eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler        if (mLayoutResId == R.layout.lb_dialog_fragment) {
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            helium.inflate(R.layout.dialog_container, (ViewGroup) mContent);
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            setDialogFragment(mDialogFragment);
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Bundle bundle = getIntent().getExtras();
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (bundle != null) {
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            boolean createFragmentFromExtra = bundle.getBoolean(EXTRA_CREATE_FRAGMENT_FROM_EXTRA);
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (createFragmentFromExtra) {
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // If intent bundle is not null, and flag indicates that should create fragments,
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // set ContentFragment and ActionFragment using bundle extras.
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String title = bundle.getString(EXTRA_DIALOG_TITLE);
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String breadcrumb = bundle.getString(EXTRA_DIALOG_BREADCRUMB);
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String description = bundle.getString(EXTRA_DIALOG_DESCRIPTION);
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String imageUriStr = bundle.getString(EXTRA_DIALOG_IMAGE_URI);
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Uri imageUri = Uri.parse(imageUriStr);
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int backgroundColor = bundle.getInt(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR);
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ArrayList<Action> actions =
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        bundle.getParcelableArrayList(EXTRA_PARCELABLE_ACTIONS);
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                setContentFragment(ContentFragment.newInstance(title, breadcrumb,
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        description, imageUri, backgroundColor));
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                setActionFragment(ActionFragment.newInstance(actions));
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
221eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler    protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onSaveInstanceState(savedInstanceState);
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        savedInstanceState.putInt(KEY_BACKSTACK_COUNT, mLastBackStackCount);
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onStart() {
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onStart();
229eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler        if (mLayoutResId == R.layout.lb_dialog_fragment) {
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            getDialogFragment().performEntryTransition();
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onBackStackChanged() {
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int count = getFragmentManager().getBackStackEntryCount();
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (count > 0 && count < mLastBackStackCount && DialogActivity.BACKSTACK_NAME_DIALOG.equals(
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                getFragmentManager().getBackStackEntryAt(count - 1).getName())) {
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            getFragmentManager().popBackStack();
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mLastBackStackCount = count;
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onActionClicked(Action action) {
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = action.getIntent();
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (intent != null) {
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            startActivity(intent);
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            finish();
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Disables the entry animation that normally happens onStart().
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void disableEntryAnimation() {
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().disableEntryAnimation();
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * This method sets the layout property of this class. <br/>
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Activities extending {@link DialogActivity} should call this method
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * before calling {@link #onCreate(Bundle)} if they want to have a
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * custom view.
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param layoutResId resource if of the activity layout
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param contentAreaId id of the content area
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param actionAreaId id of the action area
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setLayoutProperties(int layoutResId, int contentAreaId, int actionAreaId) {
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mLayoutResId = layoutResId;
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setLayoutProperties(contentAreaId, actionAreaId);
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Animates a view.
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param v              view to animate
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param initAlpha      initial alpha
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param initTransX     initial translation in the X
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param delay          delay in ms
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param duration       duration in ms
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param interpolator   interpolator to be used, can be null
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param isIcon         if {@code true}, this is the main icon being moved
28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void prepareAndAnimateView(final View v, float initAlpha, float initTransX, int delay,
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int duration, Interpolator interpolator, final boolean isIcon) {
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().prepareAndAnimateView(
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                v, initAlpha, initTransX, delay, duration, interpolator, isIcon);
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Called when intro animation is finished.
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If a subclass is going to alter the view, should wait until this is called.
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onIntroAnimationFinished() {
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().onIntroAnimationFinished();
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected boolean isIntroAnimationInProgress() {
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getDialogFragment().isIntroAnimationInProgress();
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected ColorDrawable getBackgroundDrawable() {
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getDialogFragment().getBackgroundDrawable();
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setBackgroundDrawable(ColorDrawable drawable) {
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setBackgroundDrawable(drawable);
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Sets the content fragment into the view.
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setContentFragment(Fragment fragment) {
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setContentFragment(fragment);
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Sets the action fragment into the view.
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If an action fragment currently exists, this will be added to the back stack.
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setActionFragment(Fragment fragment) {
32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setActionFragment(fragment);
32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Sets the action fragment into the view.
33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If addToBackStack is true, and action fragment currently exists,
33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * this will be added to the back stack.
33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setActionFragment(Fragment fragment, boolean addToBackStack) {
33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setActionFragment(fragment, addToBackStack);
33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected Fragment getActionFragment() {
34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getDialogFragment().getActionFragment();
34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected Fragment getContentFragment() {
34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getDialogFragment().getContentFragment();
34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Set the content and action fragments in the same transaction.
34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If an action fragment currently exists, this will be added to the back stack.
35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment) {
35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setContentAndActionFragments(contentFragment, actionFragment);
35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Set the content and action fragments in the same transaction.
35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * If addToBackStack and an action fragment currently exists,
36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * this will be added to the back stack.
36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment,
36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            boolean addToBackStack) {
36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getDialogFragment().setContentAndActionFragments(
36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                contentFragment, actionFragment, addToBackStack);
36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setDialogFragment(DialogFragment fragment) {
36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setDialogFragment(fragment, true);
37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void setDialogFragment(DialogFragment fragment, boolean addToBackStack) {
37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mDialogFragment = fragment;
37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        fragment.setActivity(this);
37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        FragmentManager fm = getFragmentManager();
37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        FragmentTransaction ft = fm.beginTransaction();
37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean hasDialog = fm.findFragmentByTag(DialogActivity.TAG_DIALOG) != null;
37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (hasDialog) {
37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (addToBackStack) {
38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ft.addToBackStack(DialogActivity.BACKSTACK_NAME_DIALOG);
38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ft.replace(R.id.dialog_fragment, fragment, DialogActivity.TAG_DIALOG);
38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ft.commit();
38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected DialogFragment getDialogFragment() {
388eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler        final DialogFragment fragment =
389eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler                (DialogFragment) getFragmentManager().findFragmentByTag(TAG_DIALOG);
390eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler        if (fragment != null) {
391eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler            mDialogFragment = fragment;
39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mDialogFragment;
39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
397