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 17package com.android.tv.settings.dialog.old; 18 19import android.app.Activity; 20import android.app.Fragment; 21import android.app.FragmentManager; 22import android.app.FragmentTransaction; 23import android.graphics.drawable.ColorDrawable; 24import android.os.Bundle; 25import android.view.View; 26import android.view.ViewGroup; 27import android.view.animation.Interpolator; 28 29import 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*/ 41public class DialogFragment extends Fragment implements ActionAdapter.Listener, LiteFragment { 42 43 private Activity mActivity; 44 private final BaseDialogFragment mBase = new BaseDialogFragment(this); 45 46 @Override 47 public void onActionClicked(Action action) { 48 mBase.onActionClicked(getRealActivity(), action); 49 } 50 51 protected void disableEntryAnimation() { 52 mBase.disableEntryAnimation(); 53 } 54 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 */ 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 */ 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 */ 106 protected void onIntroAnimationFinished() { 107 mBase.onIntroAnimationFinished(); 108 } 109 110 protected boolean isIntroAnimationInProgress() { 111 return mBase.isIntroAnimationInProgress(); 112 } 113 114 protected ColorDrawable getBackgroundDrawable() { 115 return mBase.getBackgroundDrawable(); 116 } 117 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 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 */ 136 private Activity getRealActivity() { 137 return (mActivity != null ? mActivity : getActivity()); 138 } 139 140 /** 141 * Sets the content fragment into the view. 142 */ 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 */ 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 */ 163 protected void setActionFragment(Fragment fragment, boolean addToBackStack) { 164 FragmentTransaction ft = addActionFragmentToTransaction(fragment, null, addToBackStack, 165 getRealActivity().getFragmentManager()); 166 ft.commit(); 167 } 168 169 protected Fragment getActionFragment() { 170 return getRealActivity().getFragmentManager() 171 .findFragmentByTag(BaseDialogFragment.TAG_ACTION); 172 } 173 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 */ 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 */ 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 */ 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 */ 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 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