| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.appmenu; | 5 package org.chromium.chrome.browser.appmenu; |
| 6 | 6 |
| 7 import android.animation.Animator; | 7 import android.animation.Animator; |
| 8 import android.animation.AnimatorSet; | 8 import android.animation.AnimatorSet; |
| 9 import android.content.Context; | 9 import android.content.Context; |
| 10 import android.content.res.Resources; | 10 import android.content.res.Resources; |
| 11 import android.graphics.Rect; | 11 import android.graphics.Rect; |
| 12 import android.graphics.drawable.Drawable; |
| 12 import android.view.KeyEvent; | 13 import android.view.KeyEvent; |
| 13 import android.view.LayoutInflater; | 14 import android.view.LayoutInflater; |
| 14 import android.view.Menu; | 15 import android.view.Menu; |
| 15 import android.view.MenuItem; | 16 import android.view.MenuItem; |
| 16 import android.view.Surface; | 17 import android.view.Surface; |
| 17 import android.view.View; | 18 import android.view.View; |
| 18 import android.view.View.OnKeyListener; | 19 import android.view.View.OnKeyListener; |
| 19 import android.view.ViewGroup; | 20 import android.view.ViewGroup; |
| 20 import android.widget.AdapterView; | 21 import android.widget.AdapterView; |
| 21 import android.widget.AdapterView.OnItemClickListener; | 22 import android.widget.AdapterView.OnItemClickListener; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 mPopup.setOnDismissListener(new OnDismissListener() { | 100 mPopup.setOnDismissListener(new OnDismissListener() { |
| 100 @Override | 101 @Override |
| 101 public void onDismiss() { | 102 public void onDismiss() { |
| 102 if (mPopup.getAnchorView() instanceof ImageButton) { | 103 if (mPopup.getAnchorView() instanceof ImageButton) { |
| 103 ((ImageButton) mPopup.getAnchorView()).setSelected(false); | 104 ((ImageButton) mPopup.getAnchorView()).setSelected(false); |
| 104 } | 105 } |
| 105 mHandler.onMenuVisibilityChanged(false); | 106 mHandler.onMenuVisibilityChanged(false); |
| 106 } | 107 } |
| 107 }); | 108 }); |
| 108 | 109 |
| 110 // Some OEMs don't actually let us change the background... but they sti
ll return the |
| 111 // padding of the new background, which breaks the menu height. If we s
till have a |
| 112 // drawable here even though our style says @null we should use this pad
ding instead... |
| 113 Drawable originalBgDrawable = mPopup.getBackground(); |
| 114 |
| 109 // Need to explicitly set the background here. Relying on it being set
in the style caused | 115 // Need to explicitly set the background here. Relying on it being set
in the style caused |
| 110 // an incorrectly drawn background. | 116 // an incorrectly drawn background. |
| 111 if (isByHardwareButton) { | 117 if (isByHardwareButton) { |
| 112 mPopup.setBackgroundDrawable(context.getResources().getDrawable(R.dr
awable.menu_bg)); | 118 mPopup.setBackgroundDrawable(context.getResources().getDrawable(R.dr
awable.menu_bg)); |
| 113 } else { | 119 } else { |
| 114 mPopup.setBackgroundDrawable( | 120 mPopup.setBackgroundDrawable( |
| 115 context.getResources().getDrawable(R.drawable.edge_menu_bg))
; | 121 context.getResources().getDrawable(R.drawable.edge_menu_bg))
; |
| 116 mPopup.setAnimationStyle(R.style.OverflowMenuAnim); | 122 mPopup.setAnimationStyle(R.style.OverflowMenuAnim); |
| 117 } | 123 } |
| 118 | 124 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 133 // Extract visible items from the Menu. | 139 // Extract visible items from the Menu. |
| 134 int numItems = mMenu.size(); | 140 int numItems = mMenu.size(); |
| 135 List<MenuItem> menuItems = new ArrayList<MenuItem>(); | 141 List<MenuItem> menuItems = new ArrayList<MenuItem>(); |
| 136 for (int i = 0; i < numItems; ++i) { | 142 for (int i = 0; i < numItems; ++i) { |
| 137 MenuItem item = mMenu.getItem(i); | 143 MenuItem item = mMenu.getItem(i); |
| 138 if (item.isVisible()) { | 144 if (item.isVisible()) { |
| 139 menuItems.add(item); | 145 menuItems.add(item); |
| 140 } | 146 } |
| 141 } | 147 } |
| 142 | 148 |
| 149 Rect sizingPadding = new Rect(bgPadding); |
| 150 if (isByHardwareButton && originalBgDrawable != null) { |
| 151 Rect originalPadding = new Rect(); |
| 152 originalBgDrawable.getPadding(originalPadding); |
| 153 sizingPadding.top = originalPadding.top; |
| 154 sizingPadding.bottom = originalPadding.bottom; |
| 155 } |
| 156 |
| 143 boolean showMenuButton = !mIsByHardwareButton; | 157 boolean showMenuButton = !mIsByHardwareButton; |
| 144 if (!SHOW_SW_MENU_BUTTON) showMenuButton = false; | 158 if (!SHOW_SW_MENU_BUTTON) showMenuButton = false; |
| 145 // A List adapter for visible items in the Menu. The first row is added
as a header to the | 159 // A List adapter for visible items in the Menu. The first row is added
as a header to the |
| 146 // list view. | 160 // list view. |
| 147 mAdapter = new AppMenuAdapter( | 161 mAdapter = new AppMenuAdapter( |
| 148 this, menuItems, LayoutInflater.from(context), showMenuButton); | 162 this, menuItems, LayoutInflater.from(context), showMenuButton); |
| 149 mPopup.setAdapter(mAdapter); | 163 mPopup.setAdapter(mAdapter); |
| 150 | 164 |
| 151 setMenuHeight(menuItems.size(), visibleDisplayFrame, screenHeight); | 165 setMenuHeight(menuItems.size(), visibleDisplayFrame, screenHeight, sizin
gPadding); |
| 152 setPopupOffset(mPopup, mCurrentScreenRotation, visibleDisplayFrame); | 166 setPopupOffset(mPopup, mCurrentScreenRotation, visibleDisplayFrame, sizi
ngPadding); |
| 153 mPopup.setOnItemClickListener(this); | 167 mPopup.setOnItemClickListener(this); |
| 154 mPopup.show(); | 168 mPopup.show(); |
| 155 mPopup.getListView().setItemsCanFocus(true); | 169 mPopup.getListView().setItemsCanFocus(true); |
| 156 mPopup.getListView().setOnKeyListener(this); | 170 mPopup.getListView().setOnKeyListener(this); |
| 157 | 171 |
| 158 mHandler.onMenuVisibilityChanged(true); | 172 mHandler.onMenuVisibilityChanged(true); |
| 159 | 173 |
| 160 if (mVerticalFadeDistance > 0) { | 174 if (mVerticalFadeDistance > 0) { |
| 161 mPopup.getListView().setVerticalFadingEdgeEnabled(true); | 175 mPopup.getListView().setVerticalFadingEdgeEnabled(true); |
| 162 mPopup.getListView().setFadingEdgeLength(mVerticalFadeDistance); | 176 mPopup.getListView().setFadingEdgeLength(mVerticalFadeDistance); |
| 163 } | 177 } |
| 164 | 178 |
| 165 // Don't animate the menu items for low end devices. | 179 // Don't animate the menu items for low end devices. |
| 166 if (!SysUtils.isLowEndDevice()) { | 180 if (!SysUtils.isLowEndDevice()) { |
| 167 mPopup.getListView().addOnLayoutChangeListener(new View.OnLayoutChan
geListener() { | 181 mPopup.getListView().addOnLayoutChangeListener(new View.OnLayoutChan
geListener() { |
| 168 @Override | 182 @Override |
| 169 public void onLayoutChange(View v, int left, int top, int right,
int bottom, | 183 public void onLayoutChange(View v, int left, int top, int right,
int bottom, |
| 170 int oldLeft, int oldTop, int oldRight, int oldBottom) { | 184 int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| 171 mPopup.getListView().removeOnLayoutChangeListener(this); | 185 mPopup.getListView().removeOnLayoutChangeListener(this); |
| 172 runMenuItemEnterAnimations(); | 186 runMenuItemEnterAnimations(); |
| 173 } | 187 } |
| 174 }); | 188 }); |
| 175 } | 189 } |
| 176 } | 190 } |
| 177 | 191 |
| 178 private void setPopupOffset(ListPopupWindow popup, int screenRotation, Rect
appRect) { | 192 private void setPopupOffset( |
| 179 Rect paddingRect = new Rect(); | 193 ListPopupWindow popup, int screenRotation, Rect appRect, Rect paddin
g) { |
| 180 popup.getBackground().getPadding(paddingRect); | |
| 181 int[] anchorLocation = new int[2]; | 194 int[] anchorLocation = new int[2]; |
| 182 popup.getAnchorView().getLocationInWindow(anchorLocation); | 195 popup.getAnchorView().getLocationInWindow(anchorLocation); |
| 183 int anchorHeight = popup.getAnchorView().getHeight(); | 196 int anchorHeight = popup.getAnchorView().getHeight(); |
| 184 | 197 |
| 185 // If we have a hardware menu button, locate the app menu closer to the
estimated | 198 // If we have a hardware menu button, locate the app menu closer to the
estimated |
| 186 // hardware menu button location. | 199 // hardware menu button location. |
| 187 if (mIsByHardwareButton) { | 200 if (mIsByHardwareButton) { |
| 188 int horizontalOffset = -anchorLocation[0]; | 201 int horizontalOffset = -anchorLocation[0]; |
| 189 switch (screenRotation) { | 202 switch (screenRotation) { |
| 190 case Surface.ROTATION_0: | 203 case Surface.ROTATION_0: |
| 191 case Surface.ROTATION_180: | 204 case Surface.ROTATION_180: |
| 192 horizontalOffset += (appRect.width() - mPopup.getWidth()) /
2; | 205 horizontalOffset += (appRect.width() - mPopup.getWidth()) /
2; |
| 193 break; | 206 break; |
| 194 case Surface.ROTATION_90: | 207 case Surface.ROTATION_90: |
| 195 horizontalOffset += appRect.width() - mPopup.getWidth(); | 208 horizontalOffset += appRect.width() - mPopup.getWidth(); |
| 196 break; | 209 break; |
| 197 case Surface.ROTATION_270: | 210 case Surface.ROTATION_270: |
| 198 break; | 211 break; |
| 199 default: | 212 default: |
| 200 assert false; | 213 assert false; |
| 201 break; | 214 break; |
| 202 } | 215 } |
| 203 popup.setHorizontalOffset(horizontalOffset); | 216 popup.setHorizontalOffset(horizontalOffset); |
| 204 // The menu is displayed above the anchored view, so shift the menu
up by the top | 217 // The menu is displayed above the anchored view, so shift the menu
up by the bottom |
| 205 // padding of the background. | 218 // padding of the background. |
| 206 popup.setVerticalOffset(-paddingRect.bottom); | 219 popup.setVerticalOffset(-padding.bottom); |
| 207 } else { | 220 } else { |
| 208 // The menu is displayed over and below the anchored view, so shift
the menu up by the | 221 // The menu is displayed over and below the anchored view, so shift
the menu up by the |
| 209 // height of the anchor view. | 222 // height of the anchor view. |
| 210 popup.setVerticalOffset(-mNegativeSoftwareVerticalOffset - anchorHei
ght); | 223 popup.setVerticalOffset(-mNegativeSoftwareVerticalOffset - anchorHei
ght); |
| 211 } | 224 } |
| 212 } | 225 } |
| 213 | 226 |
| 214 /** | 227 /** |
| 215 * Handles clicks on the AppMenu popup. | 228 * Handles clicks on the AppMenu popup. |
| 216 * @param menuItem The menu item in the popup that was clicked. | 229 * @param menuItem The menu item in the popup that was clicked. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 return mPopup.isShowing(); | 280 return mPopup.isShowing(); |
| 268 } | 281 } |
| 269 | 282 |
| 270 /** | 283 /** |
| 271 * @return ListPopupWindow that displays all the menu options. | 284 * @return ListPopupWindow that displays all the menu options. |
| 272 */ | 285 */ |
| 273 ListPopupWindow getPopup() { | 286 ListPopupWindow getPopup() { |
| 274 return mPopup; | 287 return mPopup; |
| 275 } | 288 } |
| 276 | 289 |
| 277 private void setMenuHeight(int numMenuItems, Rect appDimensions, int screenH
eight) { | 290 private void setMenuHeight( |
| 291 int numMenuItems, Rect appDimensions, int screenHeight, Rect padding
) { |
| 278 assert mPopup.getAnchorView() != null; | 292 assert mPopup.getAnchorView() != null; |
| 279 View anchorView = mPopup.getAnchorView(); | 293 View anchorView = mPopup.getAnchorView(); |
| 280 int[] anchorViewLocation = new int[2]; | 294 int[] anchorViewLocation = new int[2]; |
| 281 anchorView.getLocationOnScreen(anchorViewLocation); | 295 anchorView.getLocationOnScreen(anchorViewLocation); |
| 282 anchorViewLocation[1] -= appDimensions.top; | 296 anchorViewLocation[1] -= appDimensions.top; |
| 283 int anchorViewImpactHeight = mIsByHardwareButton ? anchorView.getHeight(
) : 0; | 297 int anchorViewImpactHeight = mIsByHardwareButton ? anchorView.getHeight(
) : 0; |
| 284 | 298 |
| 285 // Set appDimensions.height() for abnormal anchorViewLocation. | 299 // Set appDimensions.height() for abnormal anchorViewLocation. |
| 286 if (anchorViewLocation[1] > screenHeight) { | 300 if (anchorViewLocation[1] > screenHeight) { |
| 287 anchorViewLocation[1] = appDimensions.height(); | 301 anchorViewLocation[1] = appDimensions.height(); |
| 288 } | 302 } |
| 289 int availableScreenSpace = Math.max(anchorViewLocation[1], | 303 int availableScreenSpace = Math.max(anchorViewLocation[1], |
| 290 appDimensions.height() - anchorViewLocation[1] - anchorViewImpac
tHeight); | 304 appDimensions.height() - anchorViewLocation[1] - anchorViewImpac
tHeight); |
| 291 | 305 |
| 292 Rect padding = new Rect(); | 306 availableScreenSpace -= padding.bottom; |
| 293 mPopup.getBackground().getPadding(padding); | 307 if (mIsByHardwareButton) availableScreenSpace -= padding.top; |
| 294 availableScreenSpace -= mIsByHardwareButton ? padding.top : padding.bott
om; | |
| 295 | 308 |
| 296 int numCanFit = availableScreenSpace / (mItemRowHeight + mItemDividerHei
ght); | 309 int numCanFit = availableScreenSpace / (mItemRowHeight + mItemDividerHei
ght); |
| 297 | 310 |
| 298 // Fade out the last item if we cannot fit all items. | 311 // Fade out the last item if we cannot fit all items. |
| 299 if (numCanFit < numMenuItems) { | 312 if (numCanFit < numMenuItems) { |
| 300 int spaceForFullItems = numCanFit * (mItemRowHeight + mItemDividerHe
ight); | 313 int spaceForFullItems = numCanFit * (mItemRowHeight + mItemDividerHe
ight); |
| 301 int spaceForPartialItem = (int) (LAST_ITEM_SHOW_FRACTION * mItemRowH
eight); | 314 int spaceForPartialItem = (int) (LAST_ITEM_SHOW_FRACTION * mItemRowH
eight); |
| 302 // Determine which item needs hiding. | 315 // Determine which item needs hiding. |
| 303 if (spaceForFullItems + spaceForPartialItem < availableScreenSpace)
{ | 316 if (spaceForFullItems + spaceForPartialItem < availableScreenSpace)
{ |
| 304 mPopup.setHeight(spaceForFullItems + spaceForPartialItem + | 317 mPopup.setHeight(spaceForFullItems + spaceForPartialItem + |
| (...skipping 20 matching lines...) Expand all Loading... |
| 325 builder = animation.play((Animator) animatorObject); | 338 builder = animation.play((Animator) animatorObject); |
| 326 } else { | 339 } else { |
| 327 builder.with((Animator) animatorObject); | 340 builder.with((Animator) animatorObject); |
| 328 } | 341 } |
| 329 } | 342 } |
| 330 } | 343 } |
| 331 | 344 |
| 332 animation.start(); | 345 animation.start(); |
| 333 } | 346 } |
| 334 } | 347 } |
| OLD | NEW |