1/* 2 * Copyright (C) 2013 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 android.support.v7.app; 18 19import android.content.Context; 20import android.content.pm.ActivityInfo; 21import android.content.res.Configuration; 22import android.os.Bundle; 23import android.support.v4.app.ActionBarDrawerToggle; 24import android.support.v4.view.WindowCompat; 25import android.support.v7.internal.view.ActionModeWrapper; 26import android.support.v7.internal.view.menu.MenuWrapperFactory; 27import android.support.v7.view.ActionMode; 28import android.view.KeyEvent; 29import android.view.Menu; 30import android.view.MenuItem; 31import android.view.MotionEvent; 32import android.view.View; 33import android.view.ViewGroup; 34import android.view.Window; 35import android.view.WindowManager; 36import android.view.accessibility.AccessibilityEvent; 37 38class ActionBarActivityDelegateICS extends ActionBarActivityDelegate { 39 Menu mMenu; 40 41 ActionBarActivityDelegateICS(ActionBarActivity activity) { 42 super(activity); 43 } 44 45 @Override 46 public ActionBar createSupportActionBar() { 47 return new ActionBarImplICS(mActivity, mActivity); 48 } 49 50 @Override 51 public void onCreate(Bundle savedInstanceState) { 52 // Set framework uiOptions from the support metadata value 53 if (UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW.equals(getUiOptionsFromMetadata())) { 54 mActivity.getWindow().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW, 55 ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW); 56 } 57 58 super.onCreate(savedInstanceState); 59 60 if (mHasActionBar) { 61 // If action bar is requested by inheriting from the appcompat theme, 62 // the system will not know about that. So explicitly request for an action bar. 63 mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR); 64 } 65 if (mOverlayActionBar) { 66 mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY); 67 } 68 69 /* 70 * This goofy move needs some explanation. 71 * 72 * The verifier on older platform versions has some interesting side effects if 73 * a class defines a method that takes a parameter of a type that doesn't exist. 74 * In this case, that type is android.view.ActionMode. Therefore, ActionBarActivity 75 * cannot override the onActionModeStarted/Finished methods without causing nastiness 76 * when it is loaded on older platform versions. 77 * 78 * Since these methods are actually part of the window callback and not intrinsic to 79 * Activity itself, we can install a little shim with the window instead that knows 80 * about the ActionMode class. Note that this means that any new methods added to 81 * Window.Callback in the future won't get proxied without updating the support lib, 82 * but we shouldn't be adding new methods to public interfaces that way anyway...right? ;) 83 */ 84 final Window w = mActivity.getWindow(); 85 w.setCallback(createWindowCallbackWrapper(w.getCallback())); 86 } 87 88 Window.Callback createWindowCallbackWrapper(Window.Callback cb) { 89 return new WindowCallbackWrapper(cb); 90 } 91 92 @Override 93 public void onConfigurationChanged(Configuration newConfig) { 94 } 95 96 @Override 97 public void onStop() { 98 } 99 100 @Override 101 public void onPostResume() { 102 } 103 104 @Override 105 public void setContentView(View v) { 106 mActivity.superSetContentView(v); 107 } 108 109 @Override 110 public void setContentView(int resId) { 111 mActivity.superSetContentView(resId); 112 } 113 114 @Override 115 public void setContentView(View v, ViewGroup.LayoutParams lp) { 116 mActivity.superSetContentView(v, lp); 117 } 118 119 @Override 120 public void addContentView(View v, ViewGroup.LayoutParams lp) { 121 mActivity.superAddContentView(v, lp); 122 } 123 124 @Override 125 public void onContentChanged() { 126 // Call straight through to the support version of the method 127 mActivity.onSupportContentChanged(); 128 } 129 130 @Override 131 public boolean supportRequestWindowFeature(int featureId) { 132 return mActivity.requestWindowFeature(featureId); 133 } 134 135 @Override 136 public View onCreatePanelView(int featureId) { 137 // Do not create custom options menu on HC+ 138 return null; 139 } 140 141 @Override 142 public boolean onCreatePanelMenu(int featureId, Menu menu) { 143 if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) { 144 if (mMenu == null) { 145 mMenu = MenuWrapperFactory.createMenuWrapper(menu); 146 } 147 return mActivity.superOnCreatePanelMenu(featureId, mMenu); 148 } 149 return mActivity.superOnCreatePanelMenu(featureId, menu); 150 } 151 152 @Override 153 public boolean onPreparePanel(int featureId, View view, Menu menu) { 154 if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) { 155 return mActivity.superOnPreparePanel(featureId, view, mMenu); 156 } 157 return mActivity.superOnPreparePanel(featureId, view, menu); 158 } 159 160 @Override 161 public boolean onMenuItemSelected(int featureId, MenuItem item) { 162 if (featureId == Window.FEATURE_OPTIONS_PANEL) { 163 item = MenuWrapperFactory.createMenuItemWrapper(item); 164 } 165 return mActivity.superOnMenuItemSelected(featureId, item); 166 } 167 168 @Override 169 public void onTitleChanged(CharSequence title) { 170 // Handled by framework 171 } 172 173 @Override 174 public ActionMode startSupportActionMode(ActionMode.Callback callback) { 175 if (callback == null) { 176 throw new IllegalArgumentException("ActionMode callback can not be null."); 177 } 178 179 Context context = getActionBarThemedContext(); 180 181 ActionModeWrapper.CallbackWrapper wrappedCallback = new ActionModeWrapper.CallbackWrapper( 182 context, callback); 183 ActionModeWrapper wrappedMode = null; 184 185 android.view.ActionMode frameworkMode = mActivity.startActionMode(wrappedCallback); 186 187 if (frameworkMode != null) { 188 wrappedMode = new ActionModeWrapper(context, frameworkMode); 189 wrappedCallback.setLastStartedActionMode(wrappedMode); 190 } 191 192 return wrappedMode; 193 } 194 195 public void onActionModeStarted(android.view.ActionMode mode) { 196 mActivity.onSupportActionModeStarted( 197 new ActionModeWrapper(getActionBarThemedContext(), mode)); 198 } 199 200 @Override 201 void setSupportProgressBarVisibility(boolean visible) { 202 mActivity.setProgressBarVisibility(visible); 203 } 204 205 @Override 206 void setSupportProgressBarIndeterminateVisibility(boolean visible) { 207 mActivity.setProgressBarIndeterminateVisibility(visible); 208 } 209 210 @Override 211 void setSupportProgressBarIndeterminate(boolean indeterminate) { 212 mActivity.setProgressBarIndeterminate(indeterminate); 213 } 214 215 @Override 216 void setSupportProgress(int progress) { 217 mActivity.setProgress(progress); 218 } 219 220 public void onActionModeFinished(android.view.ActionMode mode) { 221 mActivity.onSupportActionModeFinished( 222 new ActionModeWrapper(getActionBarThemedContext(), mode)); 223 } 224 225 @Override 226 public void supportInvalidateOptionsMenu() { 227 mMenu = null; 228 } 229 230 @Override 231 public boolean onBackPressed() { 232 return false; 233 } 234 235 @Override 236 public ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { 237 // Return null so that ActionBarDrawableToggle uses it's standard impl 238 return null; 239 } 240 241 class WindowCallbackWrapper implements Window.Callback { 242 final Window.Callback mWrapped; 243 244 public WindowCallbackWrapper(Window.Callback wrapped) { 245 mWrapped = wrapped; 246 } 247 248 @Override 249 public boolean dispatchKeyEvent(KeyEvent event) { 250 return mWrapped.dispatchKeyEvent(event); 251 } 252 253 @Override 254 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 255 return mWrapped.dispatchKeyShortcutEvent(event); 256 } 257 258 @Override 259 public boolean dispatchTouchEvent(MotionEvent event) { 260 return mWrapped.dispatchTouchEvent(event); 261 } 262 263 @Override 264 public boolean dispatchTrackballEvent(MotionEvent event) { 265 return mWrapped.dispatchTrackballEvent(event); 266 } 267 268 @Override 269 public boolean dispatchGenericMotionEvent(MotionEvent event) { 270 return mWrapped.dispatchGenericMotionEvent(event); 271 } 272 273 @Override 274 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 275 return mWrapped.dispatchPopulateAccessibilityEvent(event); 276 } 277 278 @Override 279 public View onCreatePanelView(int featureId) { 280 return mWrapped.onCreatePanelView(featureId); 281 } 282 283 @Override 284 public boolean onCreatePanelMenu(int featureId, Menu menu) { 285 return mWrapped.onCreatePanelMenu(featureId, menu); 286 } 287 288 @Override 289 public boolean onPreparePanel(int featureId, View view, Menu menu) { 290 return mWrapped.onPreparePanel(featureId, view, menu); 291 } 292 293 @Override 294 public boolean onMenuOpened(int featureId, Menu menu) { 295 return mWrapped.onMenuOpened(featureId, menu); 296 } 297 298 @Override 299 public boolean onMenuItemSelected(int featureId, MenuItem item) { 300 return mWrapped.onMenuItemSelected(featureId, item); 301 } 302 303 @Override 304 public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) { 305 mWrapped.onWindowAttributesChanged(attrs); 306 } 307 308 @Override 309 public void onContentChanged() { 310 mWrapped.onContentChanged(); 311 } 312 313 @Override 314 public void onWindowFocusChanged(boolean hasFocus) { 315 mWrapped.onWindowFocusChanged(hasFocus); 316 } 317 318 @Override 319 public void onAttachedToWindow() { 320 mWrapped.onAttachedToWindow(); 321 } 322 323 @Override 324 public void onDetachedFromWindow() { 325 mWrapped.onDetachedFromWindow(); 326 } 327 328 @Override 329 public void onPanelClosed(int featureId, Menu menu) { 330 mWrapped.onPanelClosed(featureId, menu); 331 } 332 333 @Override 334 public boolean onSearchRequested() { 335 return mWrapped.onSearchRequested(); 336 } 337 338 @Override 339 public android.view.ActionMode onWindowStartingActionMode( 340 android.view.ActionMode.Callback callback) { 341 return mWrapped.onWindowStartingActionMode(callback); 342 } 343 344 /* 345 * And here are the money methods, the reason why this wrapper exists: 346 */ 347 348 @Override 349 public void onActionModeStarted(android.view.ActionMode mode) { 350 mWrapped.onActionModeStarted(mode); 351 ActionBarActivityDelegateICS.this.onActionModeStarted(mode); 352 } 353 354 @Override 355 public void onActionModeFinished(android.view.ActionMode mode) { 356 mWrapped.onActionModeFinished(mode); 357 ActionBarActivityDelegateICS.this.onActionModeFinished(mode); 358 } 359 } 360} 361