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