下面列出了android.view.ViewConfiguration#getScaledPagingTouchSlop ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Initializes various states for this workspace.
*/
protected void init() {
mDirtyPageContent = new ArrayList<Boolean>();
mDirtyPageContent.ensureCapacity(32);
mScroller = new LauncherScroller(getContext());
setDefaultInterpolator(new ScrollInterpolator());
mCurrentPage = 0;
mCenterPagesVertically = true;
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledPagingTouchSlop();
mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mDensity = getResources().getDisplayMetrics().density;
// Scale the fling-to-delete threshold by the density
mFlingToDeleteThresholdVelocity =
(int) (mFlingToDeleteThresholdVelocity * mDensity);
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
setOnHierarchyChangeListener(this);
}
/**
* Initializes various states for this workspace.
*/
protected void init() {
mScroller = new LauncherScroller(getContext());
setDefaultInterpolator(new ScrollInterpolator());
mCurrentPage = 0;
mCenterPagesVertically = true;
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mDensity = getResources().getDisplayMetrics().density;
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
setOnHierarchyChangeListener(this);
setWillNotDraw(false);
}
private void init() {
final Context context = getContext();
final ViewConfiguration configuration = ViewConfiguration.get(context);
mScroller = new Scroller(context, flipInterpolator);
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mShadowPaint.setColor(Color.BLACK);
mShadowPaint.setStyle(Style.FILL);
mShadePaint.setColor(Color.BLACK);
mShadePaint.setStyle(Style.FILL);
mShinePaint.setColor(Color.WHITE);
mShinePaint.setStyle(Style.FILL);
}
/**
* Configure the scrolling touch slop for a specific use case.
*
* Set up the RecyclerView's scrolling motion threshold based on common usages.
* Valid arguments are {@link #TOUCH_SLOP_DEFAULT} and {@link #TOUCH_SLOP_PAGING}.
*
* @param slopConstant One of the <code>TOUCH_SLOP_</code> constants representing
* the intended usage of this RecyclerView
*/
public void setScrollingTouchSlop(int slopConstant) {
final ViewConfiguration vc = ViewConfiguration.get(getContext());
switch (slopConstant) {
default:
Log.w(TAG, "setScrollingTouchSlop(): bad argument constant "
+ slopConstant + "; using default value");
// fall-through
case TOUCH_SLOP_DEFAULT:
mTouchSlop = vc.getScaledTouchSlop();
break;
case TOUCH_SLOP_PAGING:
mTouchSlop = vc.getScaledPagingTouchSlop();
break;
}
}
private void init() {
final Context context = getContext();
final ViewConfiguration configuration = ViewConfiguration.get(context);
mScroller = new Scroller(context, flipInterpolator);
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mShadowPaint.setColor(Color.BLACK);
mShadowPaint.setStyle(Style.FILL);
mShadePaint.setColor(Color.BLACK);
mShadePaint.setStyle(Style.FILL);
mShinePaint.setColor(Color.WHITE);
mShinePaint.setStyle(Style.FILL);
}
/**
* @param context The current Android's context.
* @param updateHost The {@link LayoutUpdateHost} view for this layout.
* @param renderHost The {@link LayoutRenderHost} view for this layout.
* @param eventFilter The {@link EventFilter} that is needed for this view.
*/
public StackLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost) {
super(context, updateHost, renderHost);
mGestureHandler = new StackLayoutGestureHandler();
mGestureEventFilter = new GestureEventFilter(context, mGestureHandler);
final ViewConfiguration configuration = ViewConfiguration.get(context);
mMinDirectionThreshold = configuration.getScaledTouchSlop();
mMinShortPressThresholdSqr =
configuration.getScaledPagingTouchSlop() * configuration.getScaledPagingTouchSlop();
mMinMaxInnerMargin = (int) (MIN_INNER_MARGIN_PERCENT_DP + 0.5);
mFlingSpeed = FLING_SPEED_DP;
mStacks = new Stack[2];
mStacks[0] = new Stack(context, this);
mStacks[1] = new Stack(context, this);
mStackRects = new RectF[2];
mStackRects[0] = new RectF();
mStackRects[1] = new RectF();
mViewContainer = new FrameLayout(getContext());
mSceneLayer = new TabListSceneLayer();
}
@Override public void setScrollingTouchSlop(int slopConstant) {
super.setScrollingTouchSlop(slopConstant);
final ViewConfiguration vc = ViewConfiguration.get(getContext());
switch (slopConstant) {
case TOUCH_SLOP_PAGING:
mTouchSlop = vc.getScaledPagingTouchSlop();
break;
default:
case TOUCH_SLOP_DEFAULT:
mTouchSlop = vc.getScaledTouchSlop();
break;
}
}
private void init() {
ViewConfiguration configuration = ViewConfiguration.get(getContext());
mScroller = new Scroller(getContext(), new LinearInterpolator());
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdgeEffect = new EdgeEffect(getContext());
mRightEdgeEffect = new EdgeEffect(getContext());
mShadePaint.setColor(Color.BLACK);
mShinePaint.setColor(Color.WHITE);
}
void initViewPager()
{
setWillNotDraw( false );
setDescendantFocusability( FOCUS_AFTER_DESCENDANTS );
setFocusable( true );
final Context context = getContext();
mScroller = new Scroller( context, sInterpolator );
final ViewConfiguration configuration = ViewConfiguration.get( context );
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) ( MIN_FLING_VELOCITY * density );
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdge = new EdgeEffect( context );
mRightEdge = new EdgeEffect( context );
mFlingDistance = (int) ( MIN_DISTANCE_FOR_FLING * density );
mCloseEnough = (int) ( CLOSE_ENOUGH * density );
mDefaultGutterSize = (int) ( DEFAULT_GUTTER_SIZE * density );
setAccessibilityDelegate( new MyAccessibilityDelegate() );
if ( this.getImportantForAccessibility()
== View.IMPORTANT_FOR_ACCESSIBILITY_AUTO )
{
setImportantForAccessibility( View.IMPORTANT_FOR_ACCESSIBILITY_YES );
}
}
void initSliderPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
final Context context = getContext();
mScroller = new OwnScroller(context, DEFAULT_SCROLL_DURATION, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdge = new EdgeEffect(context);
mRightEdge = new EdgeEffect(context);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate());
if (ViewCompat.getImportantForAccessibility(this)
== ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
ViewCompat.setImportantForAccessibility(this,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
ViewCompat.setOnApplyWindowInsetsListener(this,
new androidx.core.view.OnApplyWindowInsetsListener() {
private final Rect mTempRect = new Rect();
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
final WindowInsetsCompat originalInsets) {
// First let the SliderPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
if (applied.isConsumed()) {
// If the SliderPager consumed all insets, return now
return applied;
}
// Now we'll manually dispatch the insets to our children. Since SliderPager
// children are always full-height, we do not want to use the standard
// ViewGroup dispatchApplyWindowInsets since if child 0 consumes them,
// the rest of the children will not receive any insets. To workaround this
// we manually dispatch the applied insets, not allowing children to
// consume them from each other. We do however keep track of any insets
// which are consumed, returning the union of our children's consumption
final Rect res = mTempRect;
res.left = applied.getSystemWindowInsetLeft();
res.top = applied.getSystemWindowInsetTop();
res.right = applied.getSystemWindowInsetRight();
res.bottom = applied.getSystemWindowInsetBottom();
for (int i = 0, count = getChildCount(); i < count; i++) {
final WindowInsetsCompat childInsets = ViewCompat
.dispatchApplyWindowInsets(getChildAt(i), applied);
// Now keep track of any consumed by tracking each dimension's min
// value
res.left = Math.min(childInsets.getSystemWindowInsetLeft(),
res.left);
res.top = Math.min(childInsets.getSystemWindowInsetTop(),
res.top);
res.right = Math.min(childInsets.getSystemWindowInsetRight(),
res.right);
res.bottom = Math.min(childInsets.getSystemWindowInsetBottom(),
res.bottom);
}
// Now return a new WindowInsets, using the consumed window insets
return applied.replaceSystemWindowInsets(
res.left, res.top, res.right, res.bottom);
}
});
}
/**
* Handles the touch event and determines whether to show the fast scroller (or updates it if
* it is already showing).
*/
void handleTouchEvent(MotionEvent ev, int downX, int downY, int lastY) {
ViewConfiguration config = ViewConfiguration.get(mRv.getContext());
int action = ev.getAction();
int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isNearThumb(downX, downY)) {
mTouchOffsetY = downY - mThumbOffsetY;
} else if (mRv.supportsFastScrolling()
&& isNearScrollBar(downX)) {
calcTouchOffsetAndPrepToFastScroll(downY, lastY);
updateFastScrollSectionNameAndThumbOffset(lastY, y);
}
break;
case MotionEvent.ACTION_MOVE:
// Check if we should start scrolling, but ignore this fastscroll gesture if we have
// exceeded some fixed movement
mIgnoreDragGesture |= Math.abs(y - downY) > config.getScaledPagingTouchSlop();
if (!mIsDragging && !mIgnoreDragGesture && mRv.supportsFastScrolling() &&
isNearThumb(downX, lastY) &&
Math.abs(y - downY) > config.getScaledTouchSlop()) {
calcTouchOffsetAndPrepToFastScroll(downY, lastY);
}
if (mIsDragging) {
updateFastScrollSectionNameAndThumbOffset(lastY, y);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mTouchOffsetY = 0;
mLastTouchY = 0;
mIgnoreDragGesture = false;
if (mIsDragging) {
mIsDragging = false;
animatePopupVisibility(false);
showActiveScrollbar(false);
}
break;
}
}
void initViewPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
final Context context = getContext();
mScroller = new Scroller(context, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdge = new EdgeEffectCompat(context);
mRightEdge = new EdgeEffectCompat(context);
mTopEdge = new EdgeEffectCompat(context);
mBottomEdge = new EdgeEffectCompat(context);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
ViewCompat.setAccessibilityDelegate(this, new YViewPager.MyAccessibilityDelegate());
if (ViewCompat.getImportantForAccessibility(this)
== ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
ViewCompat.setImportantForAccessibility(this,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
ViewCompat.setOnApplyWindowInsetsListener(this,
new android.support.v4.view.OnApplyWindowInsetsListener() {
private final Rect mTempRect = new Rect();
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
final WindowInsetsCompat originalInsets) {
// First let the ViewPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
if (applied.isConsumed()) {
// If the ViewPager consumed all insets, return now
return applied;
}
// Now we'll manually dispatch the insets to our children. Since ViewPager
// children are always full-height, we do not want to use the standard
// ViewGroup dispatchApplyWindowInsets since if child 0 consumes them,
// the rest of the children will not receive any insets. To workaround this
// we manually dispatch the applied insets, not allowing children to
// consume them from each other. We do however keep track of any insets
// which are consumed, returning the union of our children's consumption
final Rect res = mTempRect;
res.left = applied.getSystemWindowInsetLeft();
res.top = applied.getSystemWindowInsetTop();
res.right = applied.getSystemWindowInsetRight();
res.bottom = applied.getSystemWindowInsetBottom();
for (int i = 0, count = getChildCount(); i < count; i++) {
final WindowInsetsCompat childInsets = ViewCompat
.dispatchApplyWindowInsets(getChildAt(i), applied);
// Now keep track of any consumed by tracking each dimension's min
// value
res.left = Math.min(childInsets.getSystemWindowInsetLeft(),
res.left);
res.top = Math.min(childInsets.getSystemWindowInsetTop(),
res.top);
res.right = Math.min(childInsets.getSystemWindowInsetRight(),
res.right);
res.bottom = Math.min(childInsets.getSystemWindowInsetBottom(),
res.bottom);
}
// Now return a new WindowInsets, using the consumed window insets
return applied.replaceSystemWindowInsets(
res.left, res.top, res.right, res.bottom);
}
});
}
void initViewPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
final Context context = getContext();
mScroller = new Scroller(context, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mTopEdge = new EdgeEffectCompat(context);
mBottomEdge = new EdgeEffectCompat(context);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate());
if (ViewCompat.getImportantForAccessibility(this)
== ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
ViewCompat.setImportantForAccessibility(this,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
ViewCompat.setOnApplyWindowInsetsListener(this,
new android.support.v4.view.OnApplyWindowInsetsListener() {
private final Rect mTempRect = new Rect();
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
final WindowInsetsCompat originalInsets) {
// First let the ViewPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
if (applied.isConsumed()) {
// If the ViewPager consumed all insets, return now
return applied;
}
// Now we'll manually dispatch the insets to our children. Since ViewPager
// children are always full-height, we do not want to use the standard
// ViewGroup dispatchApplyWindowInsets since if child 0 consumes them,
// the rest of the children will not receive any insets. To workaround this
// we manually dispatch the applied insets, not allowing children to
// consume them from each other. We do however keep track of any insets
// which are consumed, returning the union of our children's consumption
final Rect res = mTempRect;
res.left = applied.getSystemWindowInsetLeft();
res.top = applied.getSystemWindowInsetTop();
res.right = applied.getSystemWindowInsetRight();
res.bottom = applied.getSystemWindowInsetBottom();
for (int i = 0, count = getChildCount(); i < count; i++) {
final WindowInsetsCompat childInsets = ViewCompat
.dispatchApplyWindowInsets(getChildAt(i), applied);
// Now keep track of any consumed by tracking each dimension's min
// value
res.left = Math.min(childInsets.getSystemWindowInsetLeft(),
res.left);
res.top = Math.min(childInsets.getSystemWindowInsetTop(),
res.top);
res.right = Math.min(childInsets.getSystemWindowInsetRight(),
res.right);
res.bottom = Math.min(childInsets.getSystemWindowInsetBottom(),
res.bottom);
}
// Now return a new WindowInsets, using the consumed window insets
return applied.replaceSystemWindowInsets(
res.left, res.top, res.right, res.bottom);
}
});
}
void initViewPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
final Context context = getContext();
mScroller = new Scroller(context, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdge = new EdgeEffectCompat(context);
mRightEdge = new EdgeEffectCompat(context);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate());
if (ViewCompat.getImportantForAccessibility(this)
== ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
ViewCompat.setImportantForAccessibility(this,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
ViewCompat.setOnApplyWindowInsetsListener(this,
new androidx.core.view.OnApplyWindowInsetsListener() {
private final Rect mTempRect = new Rect();
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
final WindowInsetsCompat originalInsets) {
// First let the ViewPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
if (applied.isConsumed()) {
// If the ViewPager consumed all insets, return now
return applied;
}
// Now we'll manually dispatch the insets to our children. Since ViewPager
// children are always full-height, we do not want to use the standard
// ViewGroup dispatchApplyWindowInsets since if child 0 consumes them,
// the rest of the children will not receive any insets. To workaround this
// we manually dispatch the applied insets, not allowing children to
// consume them from each other. We do however keep track of any insets
// which are consumed, returning the union of our children's consumption
final Rect res = mTempRect;
res.left = applied.getSystemWindowInsetLeft();
res.top = applied.getSystemWindowInsetTop();
res.right = applied.getSystemWindowInsetRight();
res.bottom = applied.getSystemWindowInsetBottom();
for (int i = 0, count = getChildCount(); i < count; i++) {
final WindowInsetsCompat childInsets = ViewCompat
.dispatchApplyWindowInsets(getChildAt(i), applied);
// Now keep track of any consumed by tracking each dimension's min
// value
res.left = Math.min(childInsets.getSystemWindowInsetLeft(),
res.left);
res.top = Math.min(childInsets.getSystemWindowInsetTop(),
res.top);
res.right = Math.min(childInsets.getSystemWindowInsetRight(),
res.right);
res.bottom = Math.min(childInsets.getSystemWindowInsetBottom(),
res.bottom);
}
// Now return a new WindowInsets, using the consumed window insets
return applied.replaceSystemWindowInsets(
res.left, res.top, res.right, res.bottom);
}
});
}
public static int getScaledPagingTouchSlop(ViewConfiguration config) {
return config.getScaledPagingTouchSlop();
}
public static int getScaledPagingTouchSlop(ViewConfiguration config) {
return config.getScaledPagingTouchSlop();
}
public static int getScaledPagingTouchSlop(ViewConfiguration config) {
return config.getScaledPagingTouchSlop();
}
/**
* Handles the touch event and determines whether to show the fast scroller (or updates it if
* it is already showing).
*/
public void handleTouchEvent(MotionEvent ev, int downX, int downY, int lastY) {
ViewConfiguration config = ViewConfiguration.get(mRv.getContext());
int action = ev.getAction();
int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isNearThumb(downX, downY)) {
mTouchOffset = downY - mThumbOffset.y;
}
break;
case MotionEvent.ACTION_MOVE:
// Check if we should start scrolling, but ignore this fastscroll gesture if we have
// exceeded some fixed movement
mIgnoreDragGesture |= Math.abs(y - downY) > config.getScaledPagingTouchSlop();
if (!mIsDragging && !mIgnoreDragGesture && isNearThumb(downX, lastY) &&
Math.abs(y - downY) > config.getScaledTouchSlop()) {
mRv.getParent().requestDisallowInterceptTouchEvent(true);
mIsDragging = true;
mRv.setFastScrollDragging(mIsDragging);
if (mCanThumbDetach) {
mIsThumbDetached = true;
}
mTouchOffset += (lastY - downY);
mPopup.animateVisibility(true);
animateScrollbar(true);
}
if (mIsDragging) {
// Update the fastscroller section name at this touch position
int top = mRv.getBackgroundPadding().top;
int bottom = mRv.getHeight() - mRv.getBackgroundPadding().bottom - mThumbHeight;
float boundedY = (float) Math.max(top, Math.min(bottom, y - mTouchOffset));
String sectionName = mRv.scrollToPositionAtProgress((boundedY - top) /
(bottom - top));
mPopup.setSectionName(sectionName);
mPopup.animateVisibility(!sectionName.isEmpty());
mRv.invalidate(mPopup.updateFastScrollerBounds(mRv, lastY));
mLastTouchY = boundedY;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mTouchOffset = 0;
mLastTouchY = 0;
mIgnoreDragGesture = false;
if (mIsDragging) {
mIsDragging = false;
mRv.setFastScrollDragging(mIsDragging);
mPopup.animateVisibility(false);
animateScrollbar(false);
}
break;
}
}
/**
* Handles the touch event and determines whether to show the fast scroller (or updates it if
* it is already showing).
*/
protected void handleTouchEvent(MotionEvent ev, int downX, int downY, int lastY) {
ViewConfiguration config = ViewConfiguration.get(recyclerView.getContext());
int action = ev.getAction();
int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isNearThumb(downX, downY)) {
touchOffset = downY - thumbOffset.y;
}
break;
case MotionEvent.ACTION_MOVE:
// Check if we should start scrolling, but ignore this fastscroll gesture if we have
// exceeded some fixed movement
ignoreDragGesture |= Math.abs(y - downY) > config.getScaledPagingTouchSlop();
if (!isDragging && !ignoreDragGesture && isNearThumb(downX, lastY) &&
Math.abs(y - downY) > config.getScaledTouchSlop()) {
recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
isDragging = true;
if (canThumbDetach) {
isThumbDetached = true;
}
touchOffset += (lastY - downY);
fastScrollPopup.animateVisibility(true);
animateScrollbar(true);
}
if (isDragging) {
// Update the fastscroller section name at this touch position
int top = recyclerView.getBackgroundPadding().top;
int bottom = recyclerView.getHeight() - recyclerView.getBackgroundPadding().bottom - thumbHeight;
float boundedY = (float) Math.max(top, Math.min(bottom, y - touchOffset));
String sectionName = recyclerView.scrollToPositionAtProgress((boundedY - top) / (bottom - top));
fastScrollPopup.setSectionName(sectionName);
fastScrollPopup.animateVisibility(!sectionName.isEmpty());
recyclerView.invalidate(fastScrollPopup.updateFastScrollerBounds(recyclerView, lastY));
lastTouchY = boundedY;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
touchOffset = 0;
lastTouchY = 0;
ignoreDragGesture = false;
if (isDragging) {
isDragging = false;
fastScrollPopup.animateVisibility(false);
recyclerView.hideScrollBar();
}
break;
}
}
void initViewPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
final Context context = getContext();
mScroller = new Scroller(context, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mLeftEdge = new EdgeEffectCompat(context);
mRightEdge = new EdgeEffectCompat(context);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate());
if (ViewCompat.getImportantForAccessibility(this)
== ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
ViewCompat.setImportantForAccessibility(this,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
ViewCompat.setOnApplyWindowInsetsListener(this,
new android.support.v4.view.OnApplyWindowInsetsListener() {
private final Rect mTempRect = new Rect();
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
final WindowInsetsCompat originalInsets) {
// First let the ViewPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
if (applied.isConsumed()) {
// If the ViewPager consumed all insets, return now
return applied;
}
// Now we'll manually dispatch the insets to our children. Since ViewPager
// children are always full-height, we do not want to use the standard
// ViewGroup dispatchApplyWindowInsets since if child 0 consumes them,
// the rest of the children will not receive any insets. To workaround this
// we manually dispatch the applied insets, not allowing children to
// consume them from each other. We do however keep track of any insets
// which are consumed, returning the union of our children's consumption
final Rect res = mTempRect;
res.left = applied.getSystemWindowInsetLeft();
res.top = applied.getSystemWindowInsetTop();
res.right = applied.getSystemWindowInsetRight();
res.bottom = applied.getSystemWindowInsetBottom();
for (int i = 0, count = getChildCount(); i < count; i++) {
final WindowInsetsCompat childInsets = ViewCompat
.dispatchApplyWindowInsets(getChildAt(i), applied);
// Now keep track of any consumed by tracking each dimension's min
// value
res.left = Math.min(childInsets.getSystemWindowInsetLeft(),
res.left);
res.top = Math.min(childInsets.getSystemWindowInsetTop(),
res.top);
res.right = Math.min(childInsets.getSystemWindowInsetRight(),
res.right);
res.bottom = Math.min(childInsets.getSystemWindowInsetBottom(),
res.bottom);
}
// Now return a new WindowInsets, using the consumed window insets
return applied.replaceSystemWindowInsets(
res.left, res.top, res.right, res.bottom);
}
});
}