Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.TimeAnimator; | 7 import android.animation.TimeAnimator; |
| 8 import android.annotation.SuppressLint; | 8 import android.annotation.SuppressLint; |
| 9 import android.app.Activity; | 9 import android.app.Activity; |
| 10 import android.content.res.Resources; | 10 import android.content.res.Resources; |
| 11 import android.graphics.Point; | 11 import android.graphics.Point; |
| 12 import android.graphics.Rect; | 12 import android.graphics.Rect; |
| 13 import android.os.SystemClock; | 13 import android.os.SystemClock; |
| 14 import android.util.Log; | 14 import android.util.Log; |
| 15 import android.view.Display; | 15 import android.view.Display; |
| 16 import android.view.MotionEvent; | 16 import android.view.MotionEvent; |
| 17 import android.view.Surface; | 17 import android.view.Surface; |
| 18 import android.view.View; | 18 import android.view.View; |
| 19 import android.view.View.OnTouchListener; | 19 import android.view.View.OnTouchListener; |
| 20 import android.view.ViewConfiguration; | 20 import android.view.ViewConfiguration; |
| 21 import android.view.ViewParent; | 21 import android.view.ViewParent; |
| 22 import android.widget.ImageButton; | |
| 23 import android.widget.LinearLayout; | |
| 22 import android.widget.ListPopupWindow; | 24 import android.widget.ListPopupWindow; |
| 23 import android.widget.ListView; | 25 import android.widget.ListView; |
| 24 | 26 |
| 25 import org.chromium.chrome.R; | 27 import org.chromium.chrome.R; |
| 26 import org.chromium.chrome.browser.UmaBridge; | 28 import org.chromium.chrome.browser.UmaBridge; |
| 27 | 29 |
| 28 import java.util.ArrayList; | 30 import java.util.ArrayList; |
| 29 | 31 |
| 30 /** | 32 /** |
| 31 * Handles the drag touch events on AppMenu that start from the menu button. | 33 * Handles the drag touch events on AppMenu that start from the menu button. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 61 private int mDragScrollOffsetRounded; | 63 private int mDragScrollOffsetRounded; |
| 62 private volatile float mDragScrollingVelocity; | 64 private volatile float mDragScrollingVelocity; |
| 63 private volatile float mLastTouchX; | 65 private volatile float mLastTouchX; |
| 64 private volatile float mLastTouchY; | 66 private volatile float mLastTouchY; |
| 65 private float mTopTouchMovedBound; | 67 private float mTopTouchMovedBound; |
| 66 private float mBottomTouchMovedBound; | 68 private float mBottomTouchMovedBound; |
| 67 private boolean mIsDownScrollable; | 69 private boolean mIsDownScrollable; |
| 68 private boolean mIsUpScrollable; | 70 private boolean mIsUpScrollable; |
| 69 private boolean mIsByHardwareButton; | 71 private boolean mIsByHardwareButton; |
| 70 private int mCurrentScreenRotation = -1; | 72 private int mCurrentScreenRotation = -1; |
| 73 private final int mItemRowHeight; | |
| 71 | 74 |
| 72 // These are used in a function locally, but defined here to avoid heap allo cation on every | 75 // These are used in a function locally, but defined here to avoid heap allo cation on every |
| 73 // touch event. | 76 // touch event. |
| 74 private final Rect mScreenVisibleRect = new Rect(); | 77 private final Rect mScreenVisibleRect = new Rect(); |
| 75 private final int[] mScreenVisiblePoint = new int[2]; | 78 private final int[] mScreenVisiblePoint = new int[2]; |
| 76 | 79 |
| 77 // Sub-UI-controls, backward, forward, bookmark and listView, are getting a touch event first | 80 // Sub-UI-controls, backward, forward, bookmark and listView, are getting a touch event first |
| 78 // if the app menu is initiated by hardware menu button. For those cases, we need to | 81 // if the app menu is initiated by hardware menu button. For those cases, we need to |
| 79 // conditionally forward the touch event to our drag scrolling method. | 82 // conditionally forward the touch event to our drag scrolling method. |
| 80 private final OnTouchListener mDragScrollTouchEventForwarder = new OnTouchLi stener() { | 83 private final OnTouchListener mDragScrollTouchEventForwarder = new OnTouchLi stener() { |
| 81 @Override | 84 @Override |
| 82 public boolean onTouch(View view, MotionEvent event) { | 85 public boolean onTouch(View view, MotionEvent event) { |
| 83 return handleDragging(event); | 86 return handleDragging(event); |
| 84 } | 87 } |
| 85 }; | 88 }; |
| 86 | 89 |
| 87 AppMenuDragHelper(Activity activity, AppMenu appMenu) { | 90 AppMenuDragHelper(Activity activity, AppMenu appMenu, int itemRowHeight) { |
| 88 mActivity = activity; | 91 mActivity = activity; |
| 89 mAppMenu = appMenu; | 92 mAppMenu = appMenu; |
| 93 mItemRowHeight = itemRowHeight; | |
| 90 mScaledTouchSlop = ViewConfiguration.get( | 94 mScaledTouchSlop = ViewConfiguration.get( |
| 91 mActivity.getApplicationContext()).getScaledTouchSlop(); | 95 mActivity.getApplicationContext()).getScaledTouchSlop(); |
| 92 Resources res = mActivity.getResources(); | 96 Resources res = mActivity.getResources(); |
| 93 mAutoScrollFullVelocity = res.getDimensionPixelSize(R.dimen.auto_scroll_ full_velocity); | 97 mAutoScrollFullVelocity = res.getDimensionPixelSize(R.dimen.auto_scroll_ full_velocity); |
| 94 mEdgeSwipeInSlop = res.getDimensionPixelSize(R.dimen.edge_swipe_in_slop) ; | 98 mEdgeSwipeInSlop = res.getDimensionPixelSize(R.dimen.edge_swipe_in_slop) ; |
| 95 mEdgeSwipeInAdditionalSlop = res.getDimensionPixelSize( | 99 mEdgeSwipeInAdditionalSlop = res.getDimensionPixelSize( |
| 96 R.dimen.edge_swipe_in_additional_slop); | 100 R.dimen.edge_swipe_in_additional_slop); |
| 97 mEdgeSwipeOutSlop = res.getDimensionPixelSize(R.dimen.edge_swipe_out_slo p); | 101 mEdgeSwipeOutSlop = res.getDimensionPixelSize(R.dimen.edge_swipe_out_slo p); |
| 98 // If user is dragging and the popup ListView is too big to display at o nce, | 102 // If user is dragging and the popup ListView is too big to display at o nce, |
| 99 // mDragScrolling animator scrolls mPopup.getListView() automatically de pending on | 103 // mDragScrolling animator scrolls mPopup.getListView() automatically de pending on |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 | 159 |
| 156 // We assume that the parent of popup ListView is an instance of View. O therwise, dragging | 160 // We assume that the parent of popup ListView is an instance of View. O therwise, dragging |
| 157 // from a hardware menu button won't work. | 161 // from a hardware menu button won't work. |
| 158 ViewParent listViewParent = popup.getListView().getParent(); | 162 ViewParent listViewParent = popup.getListView().getParent(); |
| 159 if (listViewParent instanceof View) { | 163 if (listViewParent instanceof View) { |
| 160 ((View) listViewParent).setOnTouchListener(mDragScrollTouchEventForw arder); | 164 ((View) listViewParent).setOnTouchListener(mDragScrollTouchEventForw arder); |
| 161 } else { | 165 } else { |
| 162 assert false; | 166 assert false; |
| 163 } | 167 } |
| 164 | 168 |
| 165 if (mAppMenu.isShowingIconRow()) { | |
| 166 View iconRowView = mAppMenu.getIconRowView(); | |
| 167 iconRowView.findViewById(R.id.menu_item_back).setOnTouchListener( | |
| 168 mDragScrollTouchEventForwarder); | |
| 169 iconRowView.findViewById(R.id.menu_item_forward).setOnTouchListener( | |
| 170 mDragScrollTouchEventForwarder); | |
| 171 iconRowView.findViewById(R.id.menu_item_bookmark).setOnTouchListener ( | |
| 172 mDragScrollTouchEventForwarder); | |
| 173 | 169 |
| 174 } | |
|
Kibeom Kim (inactive)
2014/03/19 22:04:46
not sure dragging from hardware menu button would
Kibeom Kim (inactive)
2014/03/19 22:35:05
-> discussed with Aurimas, it seems the current ha
| |
| 175 | 170 |
| 176 if (!isByHardwareButton && startDragging) mDragScrolling.start(); | 171 if (!isByHardwareButton && startDragging) mDragScrolling.start(); |
| 177 } | 172 } |
| 178 | 173 |
| 179 void onDismiss() { | 174 void onDismiss() { |
| 180 mDragScrolling.cancel(); | 175 mDragScrolling.cancel(); |
| 181 } | 176 } |
| 182 | 177 |
| 183 /** | 178 /** |
| 184 * This is a hint for adjusting edgeSwipeInSlop. For example. If the touch e vent started | 179 * This is a hint for adjusting edgeSwipeInSlop. For example. If the touch e vent started |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 } | 268 } |
| 274 } | 269 } |
| 275 didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction); | 270 didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction); |
| 276 | 271 |
| 277 if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) { | 272 if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) { |
| 278 mAppMenu.dismiss(); | 273 mAppMenu.dismiss(); |
| 279 } else if (eventActionMasked == MotionEvent.ACTION_MOVE) { | 274 } else if (eventActionMasked == MotionEvent.ACTION_MOVE) { |
| 280 // Auto scrolling on the top or the bottom of the listView. | 275 // Auto scrolling on the top or the bottom of the listView. |
| 281 if (listView.getHeight() > 0) { | 276 if (listView.getHeight() > 0) { |
| 282 float autoScrollAreaRatio = Math.min(AUTO_SCROLL_AREA_MAX_RATIO, | 277 float autoScrollAreaRatio = Math.min(AUTO_SCROLL_AREA_MAX_RATIO, |
| 283 mAppMenu.getItemRowHeight() * 1.2f / listView.getHeight( )); | 278 mItemRowHeight * 1.2f / listView.getHeight()); |
| 284 float normalizedY = | 279 float normalizedY = |
| 285 (rawY - getScreenVisibleRect(listView).top) / listView.g etHeight(); | 280 (rawY - getScreenVisibleRect(listView).top) / listView.g etHeight(); |
| 286 if (mIsUpScrollable && normalizedY < autoScrollAreaRatio) { | 281 if (mIsUpScrollable && normalizedY < autoScrollAreaRatio) { |
| 287 // Top | 282 // Top |
| 288 mDragScrollingVelocity = (normalizedY / autoScrollAreaRatio - 1.0f) | 283 mDragScrollingVelocity = (normalizedY / autoScrollAreaRatio - 1.0f) |
| 289 * mAutoScrollFullVelocity; | 284 * mAutoScrollFullVelocity; |
| 290 } else if (mIsDownScrollable && normalizedY > 1.0f - autoScrollA reaRatio) { | 285 } else if (mIsDownScrollable && normalizedY > 1.0f - autoScrollA reaRatio) { |
| 291 // Bottom | 286 // Bottom |
| 292 mDragScrollingVelocity = ((normalizedY - 1.0f) / autoScrollA reaRatio + 1.0f) | 287 mDragScrollingVelocity = ((normalizedY - 1.0f) / autoScrollA reaRatio + 1.0f) |
| 293 * mAutoScrollFullVelocity; | 288 * mAutoScrollFullVelocity; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 * @param screenX X in screen space coordinate. | 328 * @param screenX X in screen space coordinate. |
| 334 * @param screenY Y in screen space coordinate. | 329 * @param screenY Y in screen space coordinate. |
| 335 * @param action Action type to perform, it should be one of ITEM_ACTION_* constants. | 330 * @param action Action type to perform, it should be one of ITEM_ACTION_* constants. |
| 336 * @return true whether or not a menu item is performed (executed). | 331 * @return true whether or not a menu item is performed (executed). |
| 337 */ | 332 */ |
| 338 private boolean menuItemAction(int screenX, int screenY, int action) { | 333 private boolean menuItemAction(int screenX, int screenY, int action) { |
| 339 ListView listView = mAppMenu.getPopup().getListView(); | 334 ListView listView = mAppMenu.getPopup().getListView(); |
| 340 | 335 |
| 341 ArrayList<View> itemViews = new ArrayList<View>(); | 336 ArrayList<View> itemViews = new ArrayList<View>(); |
| 342 for (int i = 0; i < listView.getChildCount(); ++i) { | 337 for (int i = 0; i < listView.getChildCount(); ++i) { |
| 343 itemViews.add(listView.getChildAt(i)); | 338 boolean hasImageButtons = false; |
| 344 } | 339 if (listView.getChildAt(i) instanceof LinearLayout) { |
| 345 | 340 LinearLayout layout = (LinearLayout) listView.getChildAt(i); |
| 346 View iconRowView = mAppMenu.getIconRowView(); | 341 for (int j = 0; j < layout.getChildCount(); ++j) { |
| 347 if (iconRowView != null && mAppMenu.isShowingIconRow()) { | 342 itemViews.add(layout.getChildAt(j)); |
| 348 itemViews.add(iconRowView.findViewById(R.id.menu_item_back)); | 343 if (layout.getChildAt(j) instanceof ImageButton) hasImageBut tons = true; |
| 349 itemViews.add(iconRowView.findViewById(R.id.menu_item_forward)); | 344 } |
| 350 itemViews.add(iconRowView.findViewById(R.id.menu_item_bookmark)); | 345 } |
| 346 if (!hasImageButtons) itemViews.add(listView.getChildAt(i)); | |
| 351 } | 347 } |
| 352 | 348 |
| 353 boolean didPerformClick = false; | 349 boolean didPerformClick = false; |
| 354 for (int i = 0; i < itemViews.size(); ++i) { | 350 for (int i = 0; i < itemViews.size(); ++i) { |
| 355 View itemView = itemViews.get(i); | 351 View itemView = itemViews.get(i); |
| 356 | 352 |
| 357 // Skip the icon row that belongs to the listView because that doesn 't really | |
| 358 // exist as an item. | |
| 359 int listViewPositionIndex = listView.getFirstVisiblePosition() + i; | |
| 360 if (mAppMenu.isShowingIconRow() && listViewPositionIndex == 0) conti nue; | |
| 361 | |
| 362 boolean shouldPerform = itemView.isEnabled() && itemView.isShown() & & | 353 boolean shouldPerform = itemView.isEnabled() && itemView.isShown() & & |
| 363 getScreenVisibleRect(itemView).contains(screenX, screenY); | 354 getScreenVisibleRect(itemView).contains(screenX, screenY); |
| 364 | 355 |
| 365 switch (action) { | 356 switch (action) { |
| 366 case ITEM_ACTION_HIGHLIGHT: | 357 case ITEM_ACTION_HIGHLIGHT: |
| 367 itemView.setPressed(shouldPerform); | 358 itemView.setPressed(shouldPerform); |
| 368 break; | 359 break; |
| 369 case ITEM_ACTION_PERFORM: | 360 case ITEM_ACTION_PERFORM: |
| 370 if (shouldPerform) { | 361 if (shouldPerform) { |
| 371 if (itemView.getParent() == listView) { | 362 itemView.performClick(); |
| 372 listView.performItemClick(itemView, listViewPosition Index, 0); | |
| 373 } else { | |
| 374 itemView.performClick(); | |
| 375 } | |
| 376 didPerformClick = true; | 363 didPerformClick = true; |
| 377 } | 364 } |
| 378 break; | 365 break; |
| 379 case ITEM_ACTION_CLEAR_HIGHLIGHT_ALL: | 366 case ITEM_ACTION_CLEAR_HIGHLIGHT_ALL: |
| 380 itemView.setPressed(false); | 367 itemView.setPressed(false); |
| 381 break; | 368 break; |
| 382 default: | 369 default: |
| 383 assert false; | 370 assert false; |
| 384 break; | 371 break; |
| 385 } | 372 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 // If it's right after we had hardware menu button UP event, use lar ge edgeSwipeInSlop, | 442 // If it's right after we had hardware menu button UP event, use lar ge edgeSwipeInSlop, |
| 456 // Otherwise, use small edgeSwipeInSlop. | 443 // Otherwise, use small edgeSwipeInSlop. |
| 457 float additionalEdgeSwipeInSlop = ((mHardwareMenuButtonUpTime - even t.getEventTime() | 444 float additionalEdgeSwipeInSlop = ((mHardwareMenuButtonUpTime - even t.getEventTime() |
| 458 + EDGE_SWIPE_IN_ADDITIONAL_SLOP_TIME_MS) * 0.001f) | 445 + EDGE_SWIPE_IN_ADDITIONAL_SLOP_TIME_MS) * 0.001f) |
| 459 * mEdgeSwipeInAdditionalSlop; | 446 * mEdgeSwipeInAdditionalSlop; |
| 460 edgeSwipeInSlope += Math.max(0.0f, additionalEdgeSwipeInSlop); | 447 edgeSwipeInSlope += Math.max(0.0f, additionalEdgeSwipeInSlop); |
| 461 } | 448 } |
| 462 return edgeSwipeInSlope; | 449 return edgeSwipeInSlope; |
| 463 } | 450 } |
| 464 } | 451 } |
| OLD | NEW |