frameworks/base
Revision | 7c34557f0ca54016ee76fbd9f621511b0397dc60 (tree) |
---|---|
Time | 2017-12-29 12:27:32 |
Author | shitao.li <shitao.li@spre...> |
Commiter | Chih-Wei Huang |
Handle mouse hover event in AbsListView
On Android 8.0 and 8.1 a change of ViewRootImpl exits touch mode on
mouse/stylus click. As a result, AbsListView will keep selection on
position 0, and will not action if click the list which can be seen
by scrolling to visible.
Add onHoverEvent to handle the mouse event and deal with selection.
Bug: https://issuetracker.google.com/issues/69774628
Test: Scroll a long listview to the end, check the last item is clickable.
Fixes: 7614cdf9 ("Exit touch mode on mouse/stylus click")
Tested-by: Chih-Wei Huang <cwhuang@linux.org.tw>
Change-Id: Ic6acc33779283342abc14d37a7d0514488a5cd1f
@@ -3765,6 +3765,39 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te | ||
3765 | 3765 | } |
3766 | 3766 | |
3767 | 3767 | @Override |
3768 | + public boolean onHoverEvent(@NonNull MotionEvent ev) { | |
3769 | + final int action = ev.getActionMasked(); | |
3770 | + | |
3771 | + // Allow the super class to handle hover state management first. | |
3772 | + final boolean handled = super.onHoverEvent(ev); | |
3773 | + if (action == MotionEvent.ACTION_HOVER_ENTER | |
3774 | + || action == MotionEvent.ACTION_HOVER_MOVE) { | |
3775 | + final int position = pointToPosition((int) ev.getX(), (int) ev.getY()); | |
3776 | + if (position != INVALID_POSITION && position != mSelectedPosition) { | |
3777 | + final View hoveredItem = getChildAt(position - getFirstVisiblePosition()); | |
3778 | + if (hoveredItem.isEnabled()) { | |
3779 | + // Force a focus so that the proper selector state gets | |
3780 | + // used when we update. | |
3781 | + requestFocus(); | |
3782 | + positionSelector(position, hoveredItem); | |
3783 | + setSelectedPositionInt(position); | |
3784 | + setNextSelectedPositionInt(position); | |
3785 | + } | |
3786 | + updateSelectorState(); | |
3787 | + } | |
3788 | + } else { | |
3789 | + // Do not cancel the selected position if the selection is visible | |
3790 | + // by other means. | |
3791 | + if (!shouldShowSelector()) { | |
3792 | + setSelectedPositionInt(INVALID_POSITION); | |
3793 | + setNextSelectedPositionInt(INVALID_POSITION); | |
3794 | + } | |
3795 | + } | |
3796 | + | |
3797 | + return handled; | |
3798 | + } | |
3799 | + | |
3800 | + @Override | |
3768 | 3801 | public boolean onTouchEvent(MotionEvent ev) { |
3769 | 3802 | if (!isEnabled()) { |
3770 | 3803 | // A disabled view that is clickable still consumes the touch |