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.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 */ 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 */ 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 */ 105 protected void onIntroAnimationFinished() { 106 mBase.onIntroAnimationFinished(); 107 } 108 109 protected boolean isIntroAnimationInProgress() { 110 return mBase.isIntroAnimationInProgress(); 111 } 112 113 protected ColorDrawable getBackgroundDrawable() { 114 return mBase.getBackgroundDrawable(); 115 } 116 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 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 */ 135 private Activity getRealActivity() { 136 return (mActivity != null ? mActivity : getActivity()); 137 } 138 139 /** 140 * Sets the content fragment into the view. 141 */ 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 */ 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 */ 162 protected void setActionFragment(Fragment fragment, boolean addToBackStack) { 163 FragmentTransaction ft = addActionFragmentToTransaction(fragment, null, addToBackStack, 164 getRealActivity().getFragmentManager()); 165 ft.commit(); 166 } 167 168 protected Fragment getActionFragment() { 169 return getRealActivity().getFragmentManager() 170 .findFragmentByTag(BaseDialogFragment.TAG_ACTION); 171 } 172 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 */ 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 */ 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 */ 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 */ 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 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