Home | History | Annotate | Download | only in old
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tv.settings.dialog.old;
     18 
     19 import android.app.Activity;
     20 import android.app.Fragment;
     21 import android.app.FragmentManager;
     22 import android.app.FragmentManager.OnBackStackChangedListener;
     23 import android.app.FragmentTransaction;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.graphics.Color;
     27 import android.graphics.drawable.ColorDrawable;
     28 import android.net.Uri;
     29 import android.os.Build;
     30 import android.os.Bundle;
     31 import android.view.LayoutInflater;
     32 import android.view.View;
     33 import android.view.ViewGroup;
     34 import android.view.animation.Interpolator;
     35 
     36 import com.android.tv.settings.R;
     37 
     38 import java.util.ArrayList;
     39 
     40 /**
     41  * A DialogActivity has 2 fragments, a content fragment and a list fragment.
     42  * <p>
     43  * Subclasses should override to supply the content fragment and list items.
     44  * <p>
     45  * The DialogActivity will handle animating in and out.
     46  * <p>
     47  * This class will use a default layout, but a custom layout can be provided by
     48  * calling {@link #setLayoutProperties}
     49  */
     50 public abstract class DialogActivity extends Activity
     51         implements ActionAdapter.Listener, OnBackStackChangedListener {
     52 
     53     /**
     54      * Dialog Content Fragment title.
     55      */
     56     public static final String EXTRA_DIALOG_TITLE = "dialog_title";
     57 
     58     /**
     59      * Dialog Content Fragment breadcrumb.
     60      */
     61     public static final String EXTRA_DIALOG_BREADCRUMB = "dialog_breadcrumb";
     62 
     63     /**
     64      * Dialog Content Fragment description.
     65      */
     66     public static final String EXTRA_DIALOG_DESCRIPTION = "dialog_description";
     67 
     68     /**
     69      * Dialog Content Fragment image uri.
     70      */
     71     public static final String EXTRA_DIALOG_IMAGE_URI = "dialog_image_uri";
     72 
     73     /**
     74      * Dialog Content Fragment image background color
     75      */
     76     public static final String EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR
     77             = "dialog_image_background_color";
     78 
     79     /**
     80      * Dialog Action Fragment actions starting index.
     81      */
     82     public static final String EXTRA_DIALOG_ACTIONS_START_INDEX = "dialog_actions_start_index";
     83 
     84     /**
     85      * Dialog Action Fragment actions.
     86      */
     87     public static final String EXTRA_PARCELABLE_ACTIONS = "parcelable_actions";
     88 
     89     /**
     90      * Whether DialogActivity should create Content Fragment and Action Fragment from extras.
     91      */
     92     public static final String EXTRA_CREATE_FRAGMENT_FROM_EXTRA = "create_fragment_from_extra";
     93 
     94     public static final String TAG_DIALOG = "tag_dialog";
     95     public static final String BACKSTACK_NAME_DIALOG = "backstack_name_dialog";
     96     public static final String KEY_BACKSTACK_COUNT = "backstack_count";
     97 
     98     protected static final int ANIMATE_IN_DURATION = 250;
     99     protected static final int ANIMATE_DELAY = 550;
    100     protected static final int SLIDE_IN_STAGGER = 100;
    101     protected static final int SLIDE_IN_DISTANCE = 120;
    102 
    103     private DialogFragment mDialogFragment;
    104     private int mLayoutResId = R.layout.two_pane_dialog_frame;
    105     private View mContent;
    106     private int mLastBackStackCount = 0;
    107 
    108     public DialogActivity() {
    109         mDialogFragment = new DialogFragment();
    110         mDialogFragment.setActivity(this);
    111     }
    112 
    113     public static Intent createIntent(Context context, String title,
    114             String breadcrumb, String description, String imageUri,
    115             ArrayList<Action> actions) {
    116         return createIntent(context, title, breadcrumb, description, imageUri,
    117                 Color.TRANSPARENT, actions);
    118     }
    119 
    120     public static Intent createIntent(Context context, String title,
    121             String breadcrumb, String description, String imageUri,
    122             int imageBackground, ArrayList<Action> actions) {
    123         Intent intent = new Intent(context, DialogActivity.class);
    124         intent.putExtra(EXTRA_DIALOG_TITLE, title);
    125         intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
    126         intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
    127         intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
    128         intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
    129         intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
    130 
    131         return intent;
    132     }
    133 
    134     public static Intent createIntent(Context context, String title,
    135             String breadcrumb, String description, String imageUri,
    136             ArrayList<Action> actions, Class<? extends DialogActivity> activityClass) {
    137         return createIntent(context, title, breadcrumb, description, imageUri, Color.TRANSPARENT,
    138                 actions, activityClass);
    139     }
    140 
    141     public static Intent createIntent(Context context, String title,
    142             String breadcrumb, String description, String imageUri, int imageBackground,
    143             ArrayList<Action> actions, Class<? extends DialogActivity> activityClass) {
    144         Intent intent = new Intent(context, activityClass);
    145         intent.putExtra(EXTRA_DIALOG_TITLE, title);
    146         intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
    147         intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
    148         intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
    149         intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
    150         intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
    151 
    152         return intent;
    153     }
    154 
    155     public static Intent createIntent(Context context, String title,
    156             String breadcrumb, String description, String imageUri, int imageBackground,
    157             ArrayList<Action> actions, Class<? extends DialogActivity> activityClass,
    158             int startIndex) {
    159         Intent intent = new Intent(context, activityClass);
    160         intent.putExtra(EXTRA_DIALOG_TITLE, title);
    161         intent.putExtra(EXTRA_DIALOG_BREADCRUMB, breadcrumb);
    162         intent.putExtra(EXTRA_DIALOG_DESCRIPTION, description);
    163         intent.putExtra(EXTRA_DIALOG_IMAGE_URI, imageUri);
    164         intent.putExtra(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR, imageBackground);
    165         intent.putParcelableArrayListExtra(EXTRA_PARCELABLE_ACTIONS, actions);
    166         intent.putExtra(EXTRA_DIALOG_ACTIONS_START_INDEX, startIndex);
    167 
    168         return intent;
    169     }
    170 
    171     public View getContentView() {
    172         return mContent;
    173     }
    174 
    175     @Override
    176     protected void onCreate(Bundle savedInstanceState) {
    177         // TODO: replace these hardcoded values with the commented constants whenever Hangouts
    178         // updates their manifest to build against JB MR2.
    179         if (Build.VERSION.SDK_INT >= 18 /* Build.VERSION_CODES.JELLY_BEAN_MR2 */) {
    180             getWindow().addFlags(0x02000000
    181                     /* WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN */);
    182         }
    183         if(savedInstanceState != null) {
    184             mLastBackStackCount = savedInstanceState.getInt(KEY_BACKSTACK_COUNT);
    185         }
    186 
    187         super.onCreate(savedInstanceState);
    188         getFragmentManager().addOnBackStackChangedListener(this);
    189 
    190         LayoutInflater helium = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    191         mContent = helium.inflate(mLayoutResId, null);
    192         setContentView(mContent);
    193         if (mLayoutResId == R.layout.two_pane_dialog_frame) {
    194             helium.inflate(R.layout.dialog_container, (ViewGroup) mContent);
    195             setDialogFragment(mDialogFragment);
    196         }
    197 
    198         Bundle bundle = getIntent().getExtras();
    199         if (bundle != null) {
    200             boolean createFragmentFromExtra = bundle.getBoolean(EXTRA_CREATE_FRAGMENT_FROM_EXTRA);
    201             if (createFragmentFromExtra) {
    202                 // If intent bundle is not null, and flag indicates that should create fragments,
    203                 // set ContentFragment and ActionFragment using bundle extras.
    204                 String title = bundle.getString(EXTRA_DIALOG_TITLE);
    205                 String breadcrumb = bundle.getString(EXTRA_DIALOG_BREADCRUMB);
    206                 String description = bundle.getString(EXTRA_DIALOG_DESCRIPTION);
    207                 String imageUriStr = bundle.getString(EXTRA_DIALOG_IMAGE_URI);
    208                 Uri imageUri = Uri.parse(imageUriStr);
    209                 int backgroundColor = bundle.getInt(EXTRA_DIALOG_IMAGE_BACKGROUND_COLOR);
    210 
    211                 ArrayList<Action> actions =
    212                         bundle.getParcelableArrayList(EXTRA_PARCELABLE_ACTIONS);
    213 
    214                 setContentFragment(ContentFragment.newInstance(title, breadcrumb,
    215                         description, imageUri, backgroundColor));
    216 
    217                 setActionFragment(ActionFragment.newInstance(actions));
    218             }
    219         }
    220     }
    221 
    222     @Override
    223     protected void onSaveInstanceState(Bundle savedInstanceState) {
    224         super.onSaveInstanceState(savedInstanceState);
    225         savedInstanceState.putInt(KEY_BACKSTACK_COUNT, mLastBackStackCount);
    226     }
    227 
    228     @Override
    229     protected void onStart() {
    230         super.onStart();
    231         if (mLayoutResId == R.layout.two_pane_dialog_frame) {
    232             getDialogFragment().performEntryTransition();
    233         }
    234     }
    235 
    236     @Override
    237     public void onBackStackChanged() {
    238         int count = getFragmentManager().getBackStackEntryCount();
    239         if (count > 0 && count < mLastBackStackCount && DialogActivity.BACKSTACK_NAME_DIALOG.equals(
    240                 getFragmentManager().getBackStackEntryAt(count - 1).getName())) {
    241             getFragmentManager().popBackStack();
    242         }
    243         mLastBackStackCount = count;
    244     }
    245 
    246     @Override
    247     public void onActionClicked(Action action) {
    248         Intent intent = action.getIntent();
    249         if (intent != null) {
    250             startActivity(intent);
    251             finish();
    252         }
    253     }
    254 
    255     /**
    256      * Disables the entry animation that normally happens onStart().
    257      */
    258     protected void disableEntryAnimation() {
    259         getDialogFragment().disableEntryAnimation();
    260     }
    261 
    262     /**
    263      * This method sets the layout property of this class. <br/>
    264      * Activities extending {@link DialogActivity} should call this method
    265      * before calling {@link #onCreate(Bundle)} if they want to have a
    266      * custom view.
    267      *
    268      * @param layoutResId resource if of the activity layout
    269      * @param contentAreaId id of the content area
    270      * @param actionAreaId id of the action area
    271      */
    272     protected void setLayoutProperties(int layoutResId, int contentAreaId, int actionAreaId) {
    273         mLayoutResId = layoutResId;
    274         getDialogFragment().setLayoutProperties(contentAreaId, actionAreaId);
    275     }
    276 
    277     /**
    278      * Animates a view.
    279      *
    280      * @param v              view to animate
    281      * @param initAlpha      initial alpha
    282      * @param initTransX     initial translation in the X
    283      * @param delay          delay in ms
    284      * @param duration       duration in ms
    285      * @param interpolator   interpolator to be used, can be null
    286      * @param isIcon         if {@code true}, this is the main icon being moved
    287      */
    288     protected void prepareAndAnimateView(final View v, float initAlpha, float initTransX, int delay,
    289             int duration, Interpolator interpolator, final boolean isIcon) {
    290         getDialogFragment().prepareAndAnimateView(
    291                 v, initAlpha, initTransX, delay, duration, interpolator, isIcon);
    292     }
    293 
    294     /**
    295      * Called when intro animation is finished.
    296      * <p>
    297      * If a subclass is going to alter the view, should wait until this is called.
    298      */
    299     protected void onIntroAnimationFinished() {
    300         getDialogFragment().onIntroAnimationFinished();
    301     }
    302 
    303     protected boolean isIntroAnimationInProgress() {
    304         return getDialogFragment().isIntroAnimationInProgress();
    305     }
    306 
    307     protected ColorDrawable getBackgroundDrawable() {
    308         return getDialogFragment().getBackgroundDrawable();
    309     }
    310 
    311     protected void setBackgroundDrawable(ColorDrawable drawable) {
    312         getDialogFragment().setBackgroundDrawable(drawable);
    313     }
    314 
    315     /**
    316      * Sets the content fragment into the view.
    317      */
    318     protected void setContentFragment(Fragment fragment) {
    319         getDialogFragment().setContentFragment(fragment);
    320     }
    321 
    322     /**
    323      * Sets the action fragment into the view.
    324      * <p>
    325      * If an action fragment currently exists, this will be added to the back stack.
    326      */
    327     protected void setActionFragment(Fragment fragment) {
    328         getDialogFragment().setActionFragment(fragment);
    329     }
    330 
    331     /**
    332      * Sets the action fragment into the view.
    333      * <p>
    334      * If addToBackStack is true, and action fragment currently exists,
    335      * this will be added to the back stack.
    336      */
    337     protected void setActionFragment(Fragment fragment, boolean addToBackStack) {
    338         getDialogFragment().setActionFragment(fragment, addToBackStack);
    339     }
    340 
    341     protected Fragment getActionFragment() {
    342         return getDialogFragment().getActionFragment();
    343     }
    344 
    345     protected Fragment getContentFragment() {
    346         return getDialogFragment().getContentFragment();
    347     }
    348 
    349     /**
    350      * Set the content and action fragments in the same transaction.
    351      * <p>
    352      * If an action fragment currently exists, this will be added to the back stack.
    353      */
    354     protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment) {
    355         getDialogFragment().setContentAndActionFragments(contentFragment, actionFragment);
    356     }
    357 
    358     /**
    359      * Set the content and action fragments in the same transaction.
    360      * <p>
    361      * If addToBackStack and an action fragment currently exists,
    362      * this will be added to the back stack.
    363      */
    364     protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment,
    365             boolean addToBackStack) {
    366         getDialogFragment().setContentAndActionFragments(
    367                 contentFragment, actionFragment, addToBackStack);
    368     }
    369 
    370     protected void setDialogFragment(DialogFragment fragment) {
    371         setDialogFragment(fragment, true);
    372     }
    373 
    374     protected void setDialogFragment(DialogFragment fragment, boolean addToBackStack) {
    375         mDialogFragment = fragment;
    376         fragment.setActivity(this);
    377         FragmentManager fm = getFragmentManager();
    378         FragmentTransaction ft = fm.beginTransaction();
    379         boolean hasDialog = fm.findFragmentByTag(DialogActivity.TAG_DIALOG) != null;
    380         if (hasDialog) {
    381             if (addToBackStack) {
    382                 ft.addToBackStack(DialogActivity.BACKSTACK_NAME_DIALOG);
    383             }
    384         }
    385         ft.replace(R.id.dialog_fragment, fragment, DialogActivity.TAG_DIALOG);
    386         ft.commit();
    387     }
    388 
    389     protected DialogFragment getDialogFragment() {
    390         FragmentManager fm = getFragmentManager();
    391         if (fm != null) {
    392             DialogFragment fragment = (DialogFragment) fm.findFragmentByTag(TAG_DIALOG);
    393             if (fragment != null) {
    394                 mDialogFragment = fragment;
    395             }
    396         }
    397 
    398         return mDialogFragment;
    399     }
    400 }
    401