From 20ad07358175f116896b9c86d50d6ce4038a66d8 Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Thu, 18 Aug 2016 14:22:57 -0400 Subject: [PATCH] Add rotary encoder support to scrolling containers Change-Id: I1b7a2a60ac9864f2639af81fff810db601b2fbd4 --- core/java/android/widget/AbsListView.java | 40 ++++++++++------- core/java/android/widget/HorizontalScrollView.java | 50 +++++++++++++--------- core/java/android/widget/ScrollView.java | 50 +++++++++++++--------- 3 files changed, 82 insertions(+), 58 deletions(-) diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 3ca928235b2b..f1bfadee5f36 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -617,6 +617,8 @@ public abstract class AbsListView extends AdapterView implements Te private int mTouchSlop; private float mDensityScale; + private float mScrollFactor; + private InputConnection mDefInputConnection; private InputConnectionWrapper mPublicInputConnection; @@ -874,6 +876,7 @@ public abstract class AbsListView extends AdapterView implements Te final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); + mScrollFactor = configuration.getScaledScrollFactor(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); @@ -4206,21 +4209,26 @@ public abstract class AbsListView extends AdapterView implements Te @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: - if (mTouchMode == TOUCH_MODE_REST) { - final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - if (vscroll != 0) { - final int delta = (int) (vscroll * getVerticalScrollFactor()); - if (!trackMotionScroll(delta, delta)) { - return true; - } - } - } - break; + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } - case MotionEvent.ACTION_BUTTON_PRESS: + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + if (!trackMotionScroll(delta, delta)) { + return true; + } + } + break; + case MotionEvent.ACTION_BUTTON_PRESS: + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { int actionButton = event.getActionButton(); if ((actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY || actionButton == MotionEvent.BUTTON_SECONDARY) @@ -4230,8 +4238,8 @@ public abstract class AbsListView extends AdapterView implements Te removeCallbacks(mPendingCheckForTap); } } - break; - } + } + break; } return super.onGenericMotionEvent(event); diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 5eea7a4f922c..918b6c0d65ff 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -129,6 +129,8 @@ public class HorizontalScrollView extends FrameLayout { private int mOverscrollDistance; private int mOverflingDistance; + private float mScrollFactor; + /** * ID of the active pointer. This is used to retain consistency during * drags/flings if multiple pointers are used. @@ -222,6 +224,7 @@ public class HorizontalScrollView extends FrameLayout { mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); + mScrollFactor = configuration.getScaledScrollFactor(); } @Override @@ -724,30 +727,35 @@ public class HorizontalScrollView extends FrameLayout { @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: { - if (!mIsBeingDragged) { - final float hscroll; + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: { + if (!mIsBeingDragged) { + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) { - hscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); + axisValue = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); } else { - hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL); + axisValue = event.getAxisValue(MotionEvent.AXIS_HSCROLL); } - if (hscroll != 0) { - final int delta = (int) (hscroll * getHorizontalScrollFactor()); - final int range = getScrollRange(); - int oldScrollX = mScrollX; - int newScrollX = oldScrollX + delta; - if (newScrollX < 0) { - newScrollX = 0; - } else if (newScrollX > range) { - newScrollX = range; - } - if (newScrollX != oldScrollX) { - super.scrollTo(newScrollX, mScrollY); - return true; - } + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } + + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + final int range = getScrollRange(); + int oldScrollX = mScrollX; + int newScrollX = oldScrollX + delta; + if (newScrollX < 0) { + newScrollX = 0; + } else if (newScrollX > range) { + newScrollX = range; + } + if (newScrollX != oldScrollX) { + super.scrollTo(newScrollX, mScrollY); + return true; } } } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 493b28c688f9..e696ff7229e8 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -135,6 +135,8 @@ public class ScrollView extends FrameLayout { private int mOverscrollDistance; private int mOverflingDistance; + private int mScrollFactor; + /** * ID of the active pointer. This is used to retain consistency during * drags/flings if multiple pointers are used. @@ -248,6 +250,7 @@ public class ScrollView extends FrameLayout { mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); + mScrollFactor = configuration.getScaledScrollFactor(); } @Override @@ -782,30 +785,35 @@ public class ScrollView extends FrameLayout { @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: { - if (!mIsBeingDragged) { - final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - if (vscroll != 0) { - final int delta = (int) (vscroll * getVerticalScrollFactor()); - final int range = getScrollRange(); - int oldScrollY = mScrollY; - int newScrollY = oldScrollY - delta; - if (newScrollY < 0) { - newScrollY = 0; - } else if (newScrollY > range) { - newScrollY = range; - } - if (newScrollY != oldScrollY) { - super.scrollTo(mScrollX, newScrollY); - return true; - } - } + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } + + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + final int range = getScrollRange(); + int oldScrollY = mScrollY; + int newScrollY = oldScrollY - delta; + if (newScrollY < 0) { + newScrollY = 0; + } else if (newScrollY > range) { + newScrollY = range; + } + if (newScrollY != oldScrollY) { + super.scrollTo(mScrollX, newScrollY); + return true; } } - } + break; } + return super.onGenericMotionEvent(event); } -- 2.11.0