Loading core/java/android/view/View.java +259 −59 Original line number Diff line number Diff line Loading @@ -100,13 +100,13 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Checkable; import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; import static android.os.Build.VERSION_CODES.*; import static java.lang.Math.max; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.ScrollBarUtils; import com.google.android.collect.Lists; import com.google.android.collect.Maps; Loading Loading @@ -5128,6 +5128,88 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mVerticalScrollbarPosition; } boolean isOnScrollbar(float x, float y) { if (mScrollCache == null) { return false; } x += getScrollX(); y += getScrollY(); if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); if (bounds.contains((int)x, (int)y)) { return true; } } if (isHorizontalScrollBarEnabled()) { final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); if (bounds.contains((int)x, (int)y)) { return true; } } return false; } boolean isOnScrollbarThumb(float x, float y) { return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y); } private boolean isOnVerticalScrollbarThumb(float x, float y) { if (mScrollCache == null) { return false; } if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { x += getScrollX(); y += getScrollY(); final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); final int range = computeVerticalScrollRange(); final int offset = computeVerticalScrollOffset(); final int extent = computeVerticalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength, extent, range, offset); final int thumbTop = bounds.top + thumbOffset; if (x >= bounds.left && x <= bounds.right && y >= thumbTop && y <= thumbTop + thumbLength) { return true; } } return false; } private boolean isOnHorizontalScrollbarThumb(float x, float y) { if (mScrollCache == null) { return false; } if (isHorizontalScrollBarEnabled()) { x += getScrollX(); y += getScrollY(); final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); final int range = computeHorizontalScrollRange(); final int offset = computeHorizontalScrollOffset(); final int extent = computeHorizontalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength, extent, range, offset); final int thumbLeft = bounds.left + thumbOffset; if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top && y <= bounds.bottom) { return true; } } return false; } boolean isDraggingScrollBar() { return mScrollCache != null && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING; } /** * Sets the state of all scroll indicators. * <p> Loading Loading @@ -9715,6 +9797,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (onFilterTouchEventForSecurity(event)) { if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { result = true; } //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null Loading Loading @@ -10579,6 +10664,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE) && event.isFromSource(InputDevice.SOURCE_MOUSE) && isOnScrollbar(event.getX(), event.getY())) { awakenScrollBars(); } if (isHoverable()) { switch (action) { case MotionEvent.ACTION_HOVER_ENTER: Loading Loading @@ -10681,6 +10771,110 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void onHoverChanged(boolean hovered) { } /** * Handles scroll bar dragging by mouse input. * * @hide * @param event The motion event. * * @return true if the event was handled as a scroll bar dragging, false otherwise. */ protected boolean handleScrollBarDragging(MotionEvent event) { if (mScrollCache == null) { return false; } final float x = event.getX(); final float y = event.getY(); final int action = event.getAction(); if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING && action != MotionEvent.ACTION_DOWN) || !event.isFromSource(InputDevice.SOURCE_MOUSE) || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; return false; } switch (action) { case MotionEvent.ACTION_MOVE: if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) { return false; } if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) { final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); final int range = computeVerticalScrollRange(); final int offset = computeVerticalScrollOffset(); final int extent = computeVerticalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength( bounds.height(), bounds.width(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset( bounds.height(), thumbLength, extent, range, offset); final float diff = y - mScrollCache.mScrollBarDraggingPos; final float maxThumbOffset = bounds.height() - thumbLength; final float newThumbOffset = Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); final int height = getHeight(); if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 && height > 0 && extent > 0) { final int newY = Math.round((range - extent) / ((float)extent / height) * (newThumbOffset / maxThumbOffset)); if (newY != getScrollY()) { mScrollCache.mScrollBarDraggingPos = y; setScrollY(newY); } } return true; } if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) { final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); final int range = computeHorizontalScrollRange(); final int offset = computeHorizontalScrollOffset(); final int extent = computeHorizontalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength( bounds.width(), bounds.height(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset( bounds.width(), thumbLength, extent, range, offset); final float diff = x - mScrollCache.mScrollBarDraggingPos; final float maxThumbOffset = bounds.width() - thumbLength; final float newThumbOffset = Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); final int width = getWidth(); if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 && width > 0 && extent > 0) { final int newX = Math.round((range - extent) / ((float)extent / width) * (newThumbOffset / maxThumbOffset)); if (newX != getScrollX()) { mScrollCache.mScrollBarDraggingPos = x; setScrollX(newX); } } return true; } case MotionEvent.ACTION_DOWN: if (isOnVerticalScrollbarThumb(x, y)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR; mScrollCache.mScrollBarDraggingPos = y; return true; } if (isOnHorizontalScrollbarThumb(x, y)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR; mScrollCache.mScrollBarDraggingPos = x; return true; } } mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; return false; } /** * Implement this method to handle touch screen motion events. * <p> Loading Loading @@ -10714,7 +10908,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE); } if (mTouchDelegate != null) { if (mTouchDelegate.onTouchEvent(event)) { return true; Loading Loading @@ -14275,6 +14468,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } private void getHorizontalScrollBarBounds(Rect bounds) { final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden(); final int size = getHorizontalScrollbarHeight(); final int verticalScrollBarGap = drawVerticalScrollBar ? getVerticalScrollbarWidth() : 0; final int width = mRight - mLeft; final int height = mBottom - mTop; bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside); bounds.left = mScrollX + (mPaddingLeft & inside); bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; bounds.bottom = bounds.top + size; } private void getVerticalScrollBarBounds(Rect bounds) { final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; final int size = getVerticalScrollbarWidth(); int verticalScrollbarPosition = mVerticalScrollbarPosition; if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { verticalScrollbarPosition = isLayoutRtl() ? SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; } final int width = mRight - mLeft; final int height = mBottom - mTop; switch (verticalScrollbarPosition) { default: case SCROLLBAR_POSITION_RIGHT: bounds.left = mScrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: bounds.left = mScrollX + (mUserPaddingLeft & inside); break; } bounds.top = mScrollY + (mPaddingTop & inside); bounds.right = bounds.left + size; bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside); } /** * <p>Request the drawing of the horizontal and the vertical scrollbar. The * scrollbars are painted only if they have been awakened first.</p> Loading Loading @@ -14322,80 +14554,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, cache.scrollBar.mutate().setAlpha(255); } final int viewFlags = mViewFlags; final boolean drawHorizontalScrollBar = (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; final boolean drawVerticalScrollBar = (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled(); final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden(); if (drawVerticalScrollBar || drawHorizontalScrollBar) { final int width = mRight - mLeft; final int height = mBottom - mTop; final ScrollBarDrawable scrollBar = cache.scrollBar; final int scrollX = mScrollX; final int scrollY = mScrollY; final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; int left; int top; int right; int bottom; if (drawHorizontalScrollBar) { int size = scrollBar.getSize(false); if (size <= 0) { size = cache.scrollBarSize; } scrollBar.setParameters(computeHorizontalScrollRange(), computeHorizontalScrollOffset(), computeHorizontalScrollExtent(), false); final int verticalScrollBarGap = drawVerticalScrollBar ? getVerticalScrollbarWidth() : 0; top = scrollY + height - size - (mUserPaddingBottom & inside); left = scrollX + (mPaddingLeft & inside); right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; bottom = top + size; onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); final Rect bounds = cache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, bounds.right, bounds.bottom); if (invalidate) { invalidate(left, top, right, bottom); invalidate(bounds); } } if (drawVerticalScrollBar) { int size = scrollBar.getSize(true); if (size <= 0) { size = cache.scrollBarSize; } scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(), computeVerticalScrollExtent(), true); int verticalScrollbarPosition = mVerticalScrollbarPosition; if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { verticalScrollbarPosition = isLayoutRtl() ? SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; } switch (verticalScrollbarPosition) { default: case SCROLLBAR_POSITION_RIGHT: left = scrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: left = scrollX + (mUserPaddingLeft & inside); break; } top = scrollY + (mPaddingTop & inside); right = left + size; bottom = scrollY + height - (mUserPaddingBottom & inside); onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); final Rect bounds = cache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, bounds.right, bounds.bottom); if (invalidate) { invalidate(left, top, right, bottom); invalidate(bounds); } } } Loading Loading @@ -21335,6 +21523,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see PointerIcon */ public PointerIcon getPointerIcon(MotionEvent event, float x, float y) { if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) { return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_ARROW); } return mPointerIcon; } Loading Loading @@ -22606,6 +22797,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private int mLastColor; public final Rect mScrollBarBounds = new Rect(); public static final int NOT_DRAGGING = 0; public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1; public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2; public int mScrollBarDraggingState = NOT_DRAGGING; public float mScrollBarDraggingPos = 0; public ScrollabilityCache(ViewConfiguration configuration, View host) { fadingEdgeLength = configuration.getScaledFadingEdgeLength(); scrollBarSize = configuration.getScaledScrollBarSize(); core/java/android/view/ViewGroup.java +20 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; /** Loading Loading @@ -1651,6 +1652,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public PointerIcon getPointerIcon(MotionEvent event, float x, float y) { if (isOnScrollbarThumb(x, y) || isDraggingScrollBar()) { return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_ARROW); } // Check what the child under the pointer says about the pointer. final int childrenCount = mChildrenCount; if (childrenCount != 0) { Loading Loading @@ -1974,7 +1978,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * hover exit event in {@link #onHoverEvent} and then the hovered child will * receive a hover enter event. * </p><p> * The default implementation always returns false. * The default implementation handles mouse hover on the scroll bars. * </p> * * @param event The motion event that describes the hover. Loading @@ -1982,6 +1986,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * and prevent its children from receiving it. */ public boolean onInterceptHoverEvent(MotionEvent event) { if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { final int action = event.getAction(); final float x = event.getX(); final float y = event.getY(); if ((action == MotionEvent.ACTION_HOVER_MOVE || action == MotionEvent.ACTION_HOVER_ENTER) && isOnScrollbar(x, y)) { return true; } } return false; } Loading Loading @@ -2716,6 +2729,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * messages will be delivered here. */ public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.isFromSource(InputDevice.SOURCE_MOUSE) && ev.getAction() == MotionEvent.ACTION_DOWN && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY) && isOnScrollbarThumb(ev.getX(), ev.getY())) { return true; } return false; } Loading core/java/android/widget/AbsListView.java +7 −0 Original line number Diff line number Diff line Loading @@ -3701,6 +3701,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } /** @hide */ @Override protected boolean handleScrollBarDragging(MotionEvent event) { // Doesn't support normal scroll bar dragging. Use FastScroller. return false; } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { Loading core/java/android/widget/HorizontalScrollView.java +4 −0 Original line number Diff line number Diff line Loading @@ -454,6 +454,10 @@ public class HorizontalScrollView extends FrameLayout { return true; } if (super.onInterceptTouchEvent(ev)) { return true; } switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_MOVE: { /* Loading core/java/android/widget/ScrollBarDrawable.java +9 −15 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.widget; import com.android.internal.widget.ScrollBarUtils; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; Loading Loading @@ -135,23 +137,15 @@ public class ScrollBarDrawable extends Drawable implements Drawable.Callback { } if (drawThumb) { final int size = vertical ? r.height() : r.width(); final int scrollBarLength = vertical ? r.height() : r.width(); final int thickness = vertical ? r.width() : r.height(); final int minLength = thickness * 2; // Avoid the tiny thumb. int length = Math.round((float) size * extent / range); if (length < minLength) { length = minLength; } // Avoid the too-big thumb. int offset = Math.round((float) (size - length) * mOffset / (range - extent)); if (offset > size - length) { offset = size - length; } final int thumbLength = ScrollBarUtils.getThumbLength(scrollBarLength, thickness, extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(scrollBarLength, thumbLength, extent, range, mOffset); drawThumb(canvas, r, offset, length, vertical); drawThumb(canvas, r, thumbOffset, thumbLength, vertical); } } Loading Loading
core/java/android/view/View.java +259 −59 Original line number Diff line number Diff line Loading @@ -100,13 +100,13 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Checkable; import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; import static android.os.Build.VERSION_CODES.*; import static java.lang.Math.max; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.ScrollBarUtils; import com.google.android.collect.Lists; import com.google.android.collect.Maps; Loading Loading @@ -5128,6 +5128,88 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mVerticalScrollbarPosition; } boolean isOnScrollbar(float x, float y) { if (mScrollCache == null) { return false; } x += getScrollX(); y += getScrollY(); if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); if (bounds.contains((int)x, (int)y)) { return true; } } if (isHorizontalScrollBarEnabled()) { final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); if (bounds.contains((int)x, (int)y)) { return true; } } return false; } boolean isOnScrollbarThumb(float x, float y) { return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y); } private boolean isOnVerticalScrollbarThumb(float x, float y) { if (mScrollCache == null) { return false; } if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { x += getScrollX(); y += getScrollY(); final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); final int range = computeVerticalScrollRange(); final int offset = computeVerticalScrollOffset(); final int extent = computeVerticalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength, extent, range, offset); final int thumbTop = bounds.top + thumbOffset; if (x >= bounds.left && x <= bounds.right && y >= thumbTop && y <= thumbTop + thumbLength) { return true; } } return false; } private boolean isOnHorizontalScrollbarThumb(float x, float y) { if (mScrollCache == null) { return false; } if (isHorizontalScrollBarEnabled()) { x += getScrollX(); y += getScrollY(); final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); final int range = computeHorizontalScrollRange(); final int offset = computeHorizontalScrollOffset(); final int extent = computeHorizontalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength, extent, range, offset); final int thumbLeft = bounds.left + thumbOffset; if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top && y <= bounds.bottom) { return true; } } return false; } boolean isDraggingScrollBar() { return mScrollCache != null && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING; } /** * Sets the state of all scroll indicators. * <p> Loading Loading @@ -9715,6 +9797,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (onFilterTouchEventForSecurity(event)) { if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { result = true; } //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null Loading Loading @@ -10579,6 +10664,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE) && event.isFromSource(InputDevice.SOURCE_MOUSE) && isOnScrollbar(event.getX(), event.getY())) { awakenScrollBars(); } if (isHoverable()) { switch (action) { case MotionEvent.ACTION_HOVER_ENTER: Loading Loading @@ -10681,6 +10771,110 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void onHoverChanged(boolean hovered) { } /** * Handles scroll bar dragging by mouse input. * * @hide * @param event The motion event. * * @return true if the event was handled as a scroll bar dragging, false otherwise. */ protected boolean handleScrollBarDragging(MotionEvent event) { if (mScrollCache == null) { return false; } final float x = event.getX(); final float y = event.getY(); final int action = event.getAction(); if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING && action != MotionEvent.ACTION_DOWN) || !event.isFromSource(InputDevice.SOURCE_MOUSE) || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; return false; } switch (action) { case MotionEvent.ACTION_MOVE: if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) { return false; } if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) { final Rect bounds = mScrollCache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); final int range = computeVerticalScrollRange(); final int offset = computeVerticalScrollOffset(); final int extent = computeVerticalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength( bounds.height(), bounds.width(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset( bounds.height(), thumbLength, extent, range, offset); final float diff = y - mScrollCache.mScrollBarDraggingPos; final float maxThumbOffset = bounds.height() - thumbLength; final float newThumbOffset = Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); final int height = getHeight(); if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 && height > 0 && extent > 0) { final int newY = Math.round((range - extent) / ((float)extent / height) * (newThumbOffset / maxThumbOffset)); if (newY != getScrollY()) { mScrollCache.mScrollBarDraggingPos = y; setScrollY(newY); } } return true; } if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) { final Rect bounds = mScrollCache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); final int range = computeHorizontalScrollRange(); final int offset = computeHorizontalScrollOffset(); final int extent = computeHorizontalScrollExtent(); final int thumbLength = ScrollBarUtils.getThumbLength( bounds.width(), bounds.height(), extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset( bounds.width(), thumbLength, extent, range, offset); final float diff = x - mScrollCache.mScrollBarDraggingPos; final float maxThumbOffset = bounds.width() - thumbLength; final float newThumbOffset = Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); final int width = getWidth(); if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 && width > 0 && extent > 0) { final int newX = Math.round((range - extent) / ((float)extent / width) * (newThumbOffset / maxThumbOffset)); if (newX != getScrollX()) { mScrollCache.mScrollBarDraggingPos = x; setScrollX(newX); } } return true; } case MotionEvent.ACTION_DOWN: if (isOnVerticalScrollbarThumb(x, y)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR; mScrollCache.mScrollBarDraggingPos = y; return true; } if (isOnHorizontalScrollbarThumb(x, y)) { mScrollCache.mScrollBarDraggingState = ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR; mScrollCache.mScrollBarDraggingPos = x; return true; } } mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; return false; } /** * Implement this method to handle touch screen motion events. * <p> Loading Loading @@ -10714,7 +10908,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE); } if (mTouchDelegate != null) { if (mTouchDelegate.onTouchEvent(event)) { return true; Loading Loading @@ -14275,6 +14468,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } private void getHorizontalScrollBarBounds(Rect bounds) { final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden(); final int size = getHorizontalScrollbarHeight(); final int verticalScrollBarGap = drawVerticalScrollBar ? getVerticalScrollbarWidth() : 0; final int width = mRight - mLeft; final int height = mBottom - mTop; bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside); bounds.left = mScrollX + (mPaddingLeft & inside); bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; bounds.bottom = bounds.top + size; } private void getVerticalScrollBarBounds(Rect bounds) { final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; final int size = getVerticalScrollbarWidth(); int verticalScrollbarPosition = mVerticalScrollbarPosition; if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { verticalScrollbarPosition = isLayoutRtl() ? SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; } final int width = mRight - mLeft; final int height = mBottom - mTop; switch (verticalScrollbarPosition) { default: case SCROLLBAR_POSITION_RIGHT: bounds.left = mScrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: bounds.left = mScrollX + (mUserPaddingLeft & inside); break; } bounds.top = mScrollY + (mPaddingTop & inside); bounds.right = bounds.left + size; bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside); } /** * <p>Request the drawing of the horizontal and the vertical scrollbar. The * scrollbars are painted only if they have been awakened first.</p> Loading Loading @@ -14322,80 +14554,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, cache.scrollBar.mutate().setAlpha(255); } final int viewFlags = mViewFlags; final boolean drawHorizontalScrollBar = (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; final boolean drawVerticalScrollBar = (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled(); final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden(); if (drawVerticalScrollBar || drawHorizontalScrollBar) { final int width = mRight - mLeft; final int height = mBottom - mTop; final ScrollBarDrawable scrollBar = cache.scrollBar; final int scrollX = mScrollX; final int scrollY = mScrollY; final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; int left; int top; int right; int bottom; if (drawHorizontalScrollBar) { int size = scrollBar.getSize(false); if (size <= 0) { size = cache.scrollBarSize; } scrollBar.setParameters(computeHorizontalScrollRange(), computeHorizontalScrollOffset(), computeHorizontalScrollExtent(), false); final int verticalScrollBarGap = drawVerticalScrollBar ? getVerticalScrollbarWidth() : 0; top = scrollY + height - size - (mUserPaddingBottom & inside); left = scrollX + (mPaddingLeft & inside); right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; bottom = top + size; onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); final Rect bounds = cache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, bounds.right, bounds.bottom); if (invalidate) { invalidate(left, top, right, bottom); invalidate(bounds); } } if (drawVerticalScrollBar) { int size = scrollBar.getSize(true); if (size <= 0) { size = cache.scrollBarSize; } scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(), computeVerticalScrollExtent(), true); int verticalScrollbarPosition = mVerticalScrollbarPosition; if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { verticalScrollbarPosition = isLayoutRtl() ? SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; } switch (verticalScrollbarPosition) { default: case SCROLLBAR_POSITION_RIGHT: left = scrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: left = scrollX + (mUserPaddingLeft & inside); break; } top = scrollY + (mPaddingTop & inside); right = left + size; bottom = scrollY + height - (mUserPaddingBottom & inside); onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); final Rect bounds = cache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, bounds.right, bounds.bottom); if (invalidate) { invalidate(left, top, right, bottom); invalidate(bounds); } } } Loading Loading @@ -21335,6 +21523,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see PointerIcon */ public PointerIcon getPointerIcon(MotionEvent event, float x, float y) { if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) { return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_ARROW); } return mPointerIcon; } Loading Loading @@ -22606,6 +22797,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private int mLastColor; public final Rect mScrollBarBounds = new Rect(); public static final int NOT_DRAGGING = 0; public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1; public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2; public int mScrollBarDraggingState = NOT_DRAGGING; public float mScrollBarDraggingPos = 0; public ScrollabilityCache(ViewConfiguration configuration, View host) { fadingEdgeLength = configuration.getScaledFadingEdgeLength(); scrollBarSize = configuration.getScaledScrollBarSize();
core/java/android/view/ViewGroup.java +20 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; /** Loading Loading @@ -1651,6 +1652,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public PointerIcon getPointerIcon(MotionEvent event, float x, float y) { if (isOnScrollbarThumb(x, y) || isDraggingScrollBar()) { return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_ARROW); } // Check what the child under the pointer says about the pointer. final int childrenCount = mChildrenCount; if (childrenCount != 0) { Loading Loading @@ -1974,7 +1978,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * hover exit event in {@link #onHoverEvent} and then the hovered child will * receive a hover enter event. * </p><p> * The default implementation always returns false. * The default implementation handles mouse hover on the scroll bars. * </p> * * @param event The motion event that describes the hover. Loading @@ -1982,6 +1986,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * and prevent its children from receiving it. */ public boolean onInterceptHoverEvent(MotionEvent event) { if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { final int action = event.getAction(); final float x = event.getX(); final float y = event.getY(); if ((action == MotionEvent.ACTION_HOVER_MOVE || action == MotionEvent.ACTION_HOVER_ENTER) && isOnScrollbar(x, y)) { return true; } } return false; } Loading Loading @@ -2716,6 +2729,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * messages will be delivered here. */ public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.isFromSource(InputDevice.SOURCE_MOUSE) && ev.getAction() == MotionEvent.ACTION_DOWN && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY) && isOnScrollbarThumb(ev.getX(), ev.getY())) { return true; } return false; } Loading
core/java/android/widget/AbsListView.java +7 −0 Original line number Diff line number Diff line Loading @@ -3701,6 +3701,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } /** @hide */ @Override protected boolean handleScrollBarDragging(MotionEvent event) { // Doesn't support normal scroll bar dragging. Use FastScroller. return false; } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { Loading
core/java/android/widget/HorizontalScrollView.java +4 −0 Original line number Diff line number Diff line Loading @@ -454,6 +454,10 @@ public class HorizontalScrollView extends FrameLayout { return true; } if (super.onInterceptTouchEvent(ev)) { return true; } switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_MOVE: { /* Loading
core/java/android/widget/ScrollBarDrawable.java +9 −15 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.widget; import com.android.internal.widget.ScrollBarUtils; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; Loading Loading @@ -135,23 +137,15 @@ public class ScrollBarDrawable extends Drawable implements Drawable.Callback { } if (drawThumb) { final int size = vertical ? r.height() : r.width(); final int scrollBarLength = vertical ? r.height() : r.width(); final int thickness = vertical ? r.width() : r.height(); final int minLength = thickness * 2; // Avoid the tiny thumb. int length = Math.round((float) size * extent / range); if (length < minLength) { length = minLength; } // Avoid the too-big thumb. int offset = Math.round((float) (size - length) * mOffset / (range - extent)); if (offset > size - length) { offset = size - length; } final int thumbLength = ScrollBarUtils.getThumbLength(scrollBarLength, thickness, extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(scrollBarLength, thumbLength, extent, range, mOffset); drawThumb(canvas, r, offset, length, vertical); drawThumb(canvas, r, thumbOffset, thumbLength, vertical); } } Loading