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.FragmentTransaction; 23 import android.graphics.drawable.ColorDrawable; 24 import android.os.Bundle; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.view.animation.Interpolator; 28 29 import com.android.tv.settings.R; 30 31 /** 32 * A DialogFragment has 2 fragments, a content fragment and a list fragment. 33 * <p> 34 * Subclasses should override to supply the content fragment and list items. 35 * <p> 36 * The DialogFragment will handle animating in and out. 37 * <p> 38 * This class will use a default layout, but a custom layout can be provided by 39 * calling {@link #setLayoutProperties} 40 */ 41 public class DialogFragment extends Fragment implements ActionAdapter.Listener, LiteFragment { 42 43 private Activity mActivity; 44 private final BaseDialogFragment mBase = new BaseDialogFragment(this); 45 46 @Override onActionClicked(Action action)47 public void onActionClicked(Action action) { 48 mBase.onActionClicked(getRealActivity(), action); 49 } 50 disableEntryAnimation()51 protected void disableEntryAnimation() { 52 mBase.disableEntryAnimation(); 53 } 54 performEntryTransition()55 public void performEntryTransition() { 56 if (mBase.mFirstOnStart) { 57 mBase.mFirstOnStart = false; 58 // Once the subclass has setup its view hierarchy, we can perform an entry 59 // transition if specified by the intent. 60 Fragment fragment = getContentFragment(); 61 if (fragment instanceof ContentFragment) { 62 ContentFragment cf = (ContentFragment) fragment; 63 mBase.performEntryTransition(getRealActivity(), 64 (ViewGroup) getRealActivity().findViewById(android.R.id.content), 65 cf.getIconResourceId(), cf.getIconResourceUri(), 66 cf.getIcon(), cf.getTitle(), cf.getDescription(), cf.getBreadCrumb()); 67 } 68 } 69 } 70 71 /** 72 * This method sets the layout property of this class. <br/> 73 * Activities extending {@link DialogFragment} should call this method 74 * before calling {@link #onCreate(Bundle)} if they want to have a 75 * custom view. 76 * 77 * @param contentAreaId id of the content area 78 * @param actionAreaId id of the action area 79 */ setLayoutProperties(int contentAreaId, int actionAreaId)80 protected void setLayoutProperties(int contentAreaId, int actionAreaId) { 81 mBase.setLayoutProperties(contentAreaId, actionAreaId); 82 } 83 84 /** 85 * Animates a view. 86 * 87 * @param v view to animate 88 * @param initAlpha initial alpha 89 * @param initTransX initial translation in the X 90 * @param delay delay in ms 91 * @param duration duration in ms 92 * @param interpolator interpolator to be used, can be null 93 * @param isIcon if {@code true}, this is the main icon being moved 94 */ prepareAndAnimateView(final View v, float initAlpha, float initTransX, int delay, int duration, Interpolator interpolator, final boolean isIcon)95 protected void prepareAndAnimateView(final View v, float initAlpha, float initTransX, int delay, 96 int duration, Interpolator interpolator, final boolean isIcon) { 97 mBase.prepareAndAnimateView( 98 v, initAlpha, initTransX, delay, duration, interpolator, isIcon); 99 } 100 101 /** 102 * Called when intro animation is finished. 103 * <p> 104 * If a subclass is going to alter the view, should wait until this is called. 105 */ onIntroAnimationFinished()106 protected void onIntroAnimationFinished() { 107 mBase.onIntroAnimationFinished(); 108 } 109 isIntroAnimationInProgress()110 protected boolean isIntroAnimationInProgress() { 111 return mBase.isIntroAnimationInProgress(); 112 } 113 getBackgroundDrawable()114 protected ColorDrawable getBackgroundDrawable() { 115 return mBase.getBackgroundDrawable(); 116 } 117 setBackgroundDrawable(ColorDrawable drawable)118 protected void setBackgroundDrawable(ColorDrawable drawable) { 119 mBase.setBackgroundDrawable(drawable); 120 } 121 122 /* ********************************************************************* */ 123 /* Fragment related code below, cannot be placed into BaseDialogFragment */ 124 /* ********************************************************************* */ 125 setActivity(Activity act)126 public void setActivity(Activity act) { 127 mActivity = act; 128 } 129 130 /** 131 * Capable of returning {@link Activity} prior to this Fragment being 132 * attached to it's parent Activity. Useful for getting the parent 133 * Activity prior to {@link #onAttach(Activity)} being called. 134 * @return parent {@link Activity} 135 */ getRealActivity()136 private Activity getRealActivity() { 137 return (mActivity != null ? mActivity : getActivity()); 138 } 139 140 /** 141 * Sets the content fragment into the view. 142 */ setContentFragment(Fragment fragment)143 protected void setContentFragment(Fragment fragment) { 144 FragmentTransaction ft = getContentFragmentTransaction(fragment); 145 ft.commit(); 146 } 147 148 /** 149 * Sets the action fragment into the view. 150 * <p> 151 * If an action fragment currently exists, this will be added to the back stack. 152 */ setActionFragment(Fragment fragment)153 protected void setActionFragment(Fragment fragment) { 154 setActionFragment(fragment, true); 155 } 156 157 /** 158 * Sets the action fragment into the view. 159 * <p> 160 * If addToBackStack is true, and action fragment currently exists, 161 * this will be added to the back stack. 162 */ setActionFragment(Fragment fragment, boolean addToBackStack)163 protected void setActionFragment(Fragment fragment, boolean addToBackStack) { 164 FragmentTransaction ft = addActionFragmentToTransaction(fragment, null, addToBackStack, 165 getRealActivity().getFragmentManager()); 166 ft.commit(); 167 } 168 getActionFragment()169 protected Fragment getActionFragment() { 170 return getRealActivity().getFragmentManager() 171 .findFragmentByTag(BaseDialogFragment.TAG_ACTION); 172 } 173 getContentFragment()174 protected Fragment getContentFragment() { 175 return getRealActivity().getFragmentManager() 176 .findFragmentByTag(BaseDialogFragment.TAG_CONTENT); 177 } 178 179 /** 180 * Set the content and action fragments in the same transaction. 181 * <p> 182 * If an action fragment currently exists, this will be added to the back stack. 183 */ setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment)184 protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment) { 185 setContentAndActionFragments(contentFragment, actionFragment, true); 186 } 187 188 /** 189 * Set the content and action fragments in the same transaction. 190 * <p> 191 * If addToBackStack and an action fragment currently exists, 192 * this will be added to the back stack. 193 */ setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment, boolean addToBackStack)194 protected void setContentAndActionFragments(Fragment contentFragment, Fragment actionFragment, 195 boolean addToBackStack) { 196 FragmentTransaction ft = getContentFragmentTransaction(contentFragment); 197 ft = addActionFragmentToTransaction(actionFragment, ft, addToBackStack, 198 getRealActivity().getFragmentManager()); 199 ft.commit(); 200 } 201 202 /** 203 * Begins a fragment transaction to edit the content fragment. 204 */ getContentFragmentTransaction(Fragment fragment)205 private FragmentTransaction getContentFragmentTransaction(Fragment fragment) { 206 FragmentManager fm = getRealActivity().getFragmentManager(); 207 boolean hasContent = fm.findFragmentByTag(BaseDialogFragment.TAG_CONTENT) != null; 208 FragmentTransaction ft = fm.beginTransaction(); 209 210 if (hasContent) { 211 addAnimations(ft); 212 } 213 ft.replace(mBase.mContentAreaId, fragment, BaseDialogFragment.TAG_CONTENT); 214 return ft; 215 } 216 217 /** 218 * Adds an action fragment replacement to an existing fragment transaction, or creates one if 219 * necessary. 220 * <p> 221 * If an action fragment currently exists, this will be added to the back stack. 222 */ addActionFragmentToTransaction(Fragment fragment, FragmentTransaction ft, boolean addToBackStack, FragmentManager fm)223 private FragmentTransaction addActionFragmentToTransaction(Fragment fragment, 224 FragmentTransaction ft, boolean addToBackStack, FragmentManager fm) { 225 if (ft == null) { 226 ft = fm.beginTransaction(); 227 } 228 boolean hasActions = fm.findFragmentByTag(BaseDialogFragment.TAG_ACTION) != null; 229 if (hasActions) { 230 addAnimations(ft); 231 if (addToBackStack) { 232 ft.addToBackStack(null); 233 } 234 } 235 ft.replace(mBase.mActionAreaId, fragment, BaseDialogFragment.TAG_ACTION); 236 237 if (fragment instanceof ActionFragment) { 238 if (!((ActionFragment) fragment).hasListener()) { 239 ((ActionFragment) fragment).setListener(this); 240 } 241 } 242 243 return ft; 244 } 245 addAnimations(FragmentTransaction ft)246 static void addAnimations(FragmentTransaction ft) { 247 ft.setCustomAnimations(R.anim.fragment_slide_left_in, 248 R.anim.fragment_slide_left_out, R.anim.fragment_slide_right_in, 249 R.anim.fragment_slide_right_out); 250 } 251 } 252 253