下面列出了android.view.View#canScrollVertically ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean canScrollUp(View view, float x, float y) {
if (view instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < vg.getChildCount(); i++) {
View child = vg.getChildAt(i);
int childLeft = child.getLeft();
int childTop = child.getTop();
int childRight = child.getRight();
int childBottom = child.getBottom();
boolean intersects = x > childLeft && x < childRight && y > childTop && y < childBottom;
if (intersects && canScrollUp(child, x - childLeft, y - childTop)) {
return true;
}
}
}
return view.canScrollVertically(-1);
}
@Override
public boolean tryCaptureView(View child, int pointerId) {
if (mState == STATE_DRAGGING) {
return false;
}
if (mTouchingScrollingChild) {
return false;
}
if (mState == STATE_EXPANDED && mActivePointerId == pointerId) {
View scroll = mNestedScrollingChildRef.get();
if (scroll != null && scroll.canScrollVertically(-1)) {
// Let the content scroll up
return false;
}
}
return mViewRef != null && mViewRef.get() == child;
}
/**
* Tests scrollability within child views of v given a delta of dx.
*
* @param v View to test for horizontal scrollability
* @param checkV Whether the view v passed should itself be checked for scrollability (true),
* or just its children (false).
* @param dx Delta scrolled in pixels along the X axis
* @param dy Delta scrolled in pixels along the Y axis
* @param x X coordinate of the active touch point
* @param y Y coordinate of the active touch point
* @return true if child views of v can be scrolled by delta of dx.
*/
protected boolean canScroll(View v, boolean checkV, int dx, int dy, int x, int y) {
if (v instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) v;
final int scrollX = v.getScrollX();
final int scrollY = v.getScrollY();
final int count = group.getChildCount();
// Count backwards - let topmost views consume scroll distance first.
for (int i = count - 1; i >= 0; i--) {
// TODO: Add versioned support here for transformed views.
// This will not work for transformed views in Honeycomb+
final View child = group.getChildAt(i);
if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
canScroll(child, true, dx, dy, x + scrollX - child.getLeft(),
y + scrollY - child.getTop())) {
return true;
}
}
}
return checkV && (v.canScrollHorizontally(-dx) ||
v.canScrollVertically(-dy));
}
public static boolean canViewScrollVertically(View view, int direction) {
boolean result = false;
if (Build.VERSION.SDK_INT < 14) {
if (view instanceof AbsListView) {//list view etc.
result = performAbsListView((AbsListView) view, direction);
} else {
try {//i known it's a bad way!
Class<? extends View> viewClass = view.getClass();
final int offset = (int) viewClass.getDeclaredMethod("computeVerticalScrollOffset").invoke(view);
final int range = (int) viewClass.getDeclaredMethod("computeVerticalScrollRange").invoke(view)
- (int) viewClass.getDeclaredMethod("computeVerticalScrollExtent").invoke(view);
if (range == 0) return false;
if (direction < 0) {
result = (offset > 0);
} else {
result = offset < range - 1;
}
} catch (Exception e) {
if (DEBUG_SCROLL_CHECK)
L.e(TAG, "no such method!!");
result = view.getScrollY() > 0;
}
}
} else {
result = view.canScrollVertically(direction);
}
if (DEBUG_SCROLL_CHECK)
L.e(TAG, "view = %s , direction is %s, canViewScrollVertically = %s",
view,
(direction > 0 ? "up" : "down"),
result);
return result;
}
/**
* child can scroll
* @param view
* @param event
* @param x
* @param y
* @param lockRect 是否开启 touch 所动在当前 view 区域
* @return
*/
protected boolean canScrollDown(View view, MotionEvent event, float x, float y, boolean lockRect) {
if (view instanceof WebView) {
return canWebViewScrollDown((WebView) view);
}
if (view instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < vg.getChildCount(); i++) {
View child = vg.getChildAt(i);
int childLeft = child.getLeft() - view.getScrollX();
int childTop = child.getTop() - view.getScrollY();
int childRight = child.getRight() - view.getScrollX();
int childBottom = child.getBottom() - view.getScrollY();
boolean intersects = x > childLeft && x < childRight && y > childTop && y < childBottom;
if ((!lockRect || intersects)
&& canScrollDown(child, event, x - childLeft, y - childTop, lockRect)) {
return true;
}
}
}
if (view instanceof CoordinatorLayout &&
((CoordinatorLayout) view).getChildCount() > 0 &&
((CoordinatorLayout) view).getChildAt(0) instanceof AppBarLayout) {
AppBarLayout layout = (AppBarLayout) ((CoordinatorLayout) view).getChildAt(0);
OnNestOffsetChangedListener listener = mOnOffsetChangedListener.get(layout.hashCode());
if (listener != null) {
if (listener.getOffsetY() < layout.getMeasuredHeight() && listener.getOffsetY() > 0) {
return true;
}
}
}
return isTouchUnderChildView(view, event) && view.canScrollVertically(1);
}
public static boolean canScrollUp(View targetView) {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (targetView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) targetView;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return targetView.getScrollY() > 0;
}
} else {
return targetView.canScrollVertically(-1);
}
}
private boolean checkPullableInternal(View child, int pointerId) {
if (child instanceof ListView) {
return ListViewCompat.canScrollList((ListView) child, -1);
}
//canScrollVertically返回fasle,即到顶部无法继续下滑,此时就可以认为允许下拉刷新了
return !child.canScrollVertically(-1);
}
boolean shouldLift(@Nullable View defaultScrollingView) {
View scrollingView = findLiftOnScrollTargetView(defaultScrollingView);
if (scrollingView == null) {
scrollingView = defaultScrollingView;
}
return scrollingView != null
&& (scrollingView.canScrollVertically(-1) || scrollingView.getScrollY() > 0);
}
public boolean canChildScrollDown() {
try {
View v = (View) mTarget.get(this);
return v.canScrollVertically(1);
} catch (Exception e) {
return true;
}
}
public static boolean canChildScrollUp(View view) {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (view instanceof AbsListView) {
final AbsListView absListView = (AbsListView) view;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return view.getScrollY() > 0;
}
} else {
return view.canScrollVertically(-1);
}
}
public boolean isNotYetInEdgeCannotMoveHeader() {
final View targetView = getScrollTargetView();
if (mInEdgeCanMoveHeaderCallBack != null) {
return mInEdgeCanMoveHeaderCallBack.isNotYetInEdgeCannotMoveHeader(
this, targetView, mFooterView);
}
return targetView != null && targetView.canScrollVertically(-1);
}
public boolean isNotYetInEdgeCannotMoveFooter() {
final View targetView = getScrollTargetView();
if (mInEdgeCanMoveFooterCallBack != null) {
return mInEdgeCanMoveFooterCallBack.isNotYetInEdgeCannotMoveFooter(
this, targetView, mHeaderView);
}
return targetView != null && targetView.canScrollVertically(1);
}
/**
* To be called after the View has been laid out. If the view is presumably to small,
* this will call {@link #onSpaceOver(View)} for you.
*
* @param view The view that has been laid out
*/
public static void onLayout(View view) {
if (view.getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
// TODO: don't do this if getMaxLines is >= 0 (< MAX_VALUE). Same for getMaxheight.
if (view.canScrollVertically(-1) || view.canScrollVertically(1)) {
LOG.w("onLayout:", preview(view), "We can scroll. Notifying the parent column.");
onSpaceOver(view);
}
}
}
public static boolean canScrollVertically(View v, int direction) {
return v.canScrollVertically(direction);
}
public static boolean canScrollVertically(View v, int direction) {
return v.canScrollVertically(direction);
}
public static boolean canScrollVertically(View v, int direction) {
return v.canScrollVertically(direction);
}
public static boolean canScrollVertically(View v, int direction) {
return v.canScrollVertically(direction);
}
@Override
public void onNestedPreScroll(
@NonNull CoordinatorLayout coordinatorLayout,
@NonNull V child,
@NonNull View target,
int dx,
int dy,
@NonNull int[] consumed,
int type) {
if (type == ViewCompat.TYPE_NON_TOUCH) {
// Ignore fling here. The ViewDragHelper handles it.
return;
}
View scrollingChild = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
if (target != scrollingChild) {
return;
}
int currentTop = child.getTop();
int newTop = currentTop - dy;
if (dy > 0) { // Upward
if (newTop < getExpandedOffset()) {
consumed[1] = currentTop - getExpandedOffset();
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
setStateInternal(STATE_EXPANDED);
} else {
if (!draggable) {
// Prevent dragging
return;
}
consumed[1] = dy;
ViewCompat.offsetTopAndBottom(child, -dy);
setStateInternal(STATE_DRAGGING);
}
} else if (dy < 0) { // Downward
if (!target.canScrollVertically(-1)) {
if (newTop <= collapsedOffset || hideable) {
if (!draggable) {
// Prevent dragging
return;
}
consumed[1] = dy;
ViewCompat.offsetTopAndBottom(child, -dy);
setStateInternal(STATE_DRAGGING);
} else {
consumed[1] = currentTop - collapsedOffset;
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
setStateInternal(STATE_COLLAPSED);
}
}
}
dispatchOnSlide(child.getTop());
lastNestedScrollDy = dy;
nestedScrolled = true;
}
public static boolean b(View view, int i)
{
return view.canScrollVertically(i);
}
/**
* view是否已经滚动到最底部
*
* @param view
* @return
*/
public static boolean isScrollToBottom(View view)
{
return !view.canScrollVertically(1);
}