/** * Copyright 2015 bingoogolapple * <p/> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lcodecore.tkrefreshlayout.utils; import android.content.Context; import android.graphics.Rect; import android.os.Build; import android.support.v4.view.ViewCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.WebView; import android.widget.AbsListView; import android.widget.ScrollView; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ScrollingUtil { private ScrollingUtil() { } /** * 用来判断是否可以下拉 * 手指在屏幕上该方法才有效 */ public static boolean canChildScrollUp(View mChildView) { if (mChildView == null) { return false; } if (Build.VERSION.SDK_INT < 14) { if (mChildView instanceof AbsListView) { final AbsListView absListView = (AbsListView) mChildView; return absListView.getChildCount() > 0 && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0) .getTop() < absListView.getPaddingTop()); } else { return ViewCompat.canScrollVertically(mChildView, -1) || mChildView.getScrollY() > 0; } } else { return ViewCompat.canScrollVertically(mChildView, -1); } } /** * Whether it is possible for the child view of this layout to scroll down. Override this if the child view is a custom view. * 判断是否可以上拉 */ public static boolean canChildScrollDown(View mChildView) { if (Build.VERSION.SDK_INT < 14) { if (mChildView instanceof AbsListView) { final AbsListView absListView = (AbsListView) mChildView; return absListView.getChildCount() > 0 && (absListView.getLastVisiblePosition() < absListView.getChildCount() - 1 || absListView.getChildAt(absListView.getChildCount() - 1).getBottom() > absListView.getPaddingBottom()); } else { return ViewCompat.canScrollVertically(mChildView, 1) || mChildView.getScrollY() < 0; } } else { return ViewCompat.canScrollVertically(mChildView, 1); } } public static boolean isScrollViewOrWebViewToTop(View view) { return view != null && view.getScrollY() == 0; } public static boolean isViewToTop(View view, int mTouchSlop) { if (view instanceof AbsListView) return isAbsListViewToTop((AbsListView) view); if (view instanceof RecyclerView) return isRecyclerViewToTop((RecyclerView) view); return (view != null && Math.abs(view.getScrollY()) <= 2 * mTouchSlop); } public static boolean isViewToBottom(View view, int mTouchSlop) { if (view instanceof AbsListView) return isAbsListViewToBottom((AbsListView) view); if (view instanceof RecyclerView) return isRecyclerViewToBottom((RecyclerView) view); if (view instanceof WebView) return isWebViewToBottom((WebView) view, mTouchSlop); if (view instanceof ViewGroup) return isViewGroupToBottom((ViewGroup) view); return false; } public static boolean isAbsListViewToTop(AbsListView absListView) { if (absListView != null) { int firstChildTop = 0; if (absListView.getChildCount() > 0) { // 如果AdapterView的子控件数量不为0,获取第一个子控件的top firstChildTop = absListView.getChildAt(0).getTop() - absListView.getPaddingTop(); } if (absListView.getFirstVisiblePosition() == 0 && firstChildTop == 0) { return true; } } return false; } public static boolean isRecyclerViewToTop(RecyclerView recyclerView) { if (recyclerView != null) { RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager == null) { return true; } if (manager.getItemCount() == 0) { return true; } int firstChildTop = 0; if (recyclerView.getChildCount() > 0) { // 处理item高度超过一屏幕时的情况 View firstVisibleChild = recyclerView.getChildAt(0); if (firstVisibleChild != null && firstVisibleChild.getMeasuredHeight() >= recyclerView.getMeasuredHeight()) { if (android.os.Build.VERSION.SDK_INT < 14) { return !(ViewCompat.canScrollVertically(recyclerView, -1) || recyclerView.getScrollY() > 0); } else { return !ViewCompat.canScrollVertically(recyclerView, -1); } } // 如果RecyclerView的子控件数量不为0,获取第一个子控件的top // 解决item的topMargin不为0时不能触发下拉刷新 View firstChild = recyclerView.getChildAt(0); RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) firstChild.getLayoutParams(); firstChildTop = firstChild.getTop() - layoutParams.topMargin - getRecyclerViewItemTopInset(layoutParams) - recyclerView.getPaddingTop(); } if (manager instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) manager; if (layoutManager.findFirstCompletelyVisibleItemPosition() < 1 && firstChildTop == 0) { return true; } } else if (manager instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) manager; int[] out = layoutManager.findFirstCompletelyVisibleItemPositions(null); if (out[0] < 1 && firstChildTop == 0) { return true; } } } return false; } /** * 通过反射获取RecyclerView的item的topInset * * @param layoutParams * @return */ private static int getRecyclerViewItemTopInset(RecyclerView.LayoutParams layoutParams) { try { Field field = RecyclerView.LayoutParams.class.getDeclaredField("mDecorInsets"); field.setAccessible(true); // 开发者自定义的滚动监听器 Rect decorInsets = (Rect) field.get(layoutParams); return decorInsets.top; } catch (Exception e) { e.printStackTrace(); } return 0; } public static boolean isWebViewToBottom(WebView webview, int mTouchSlop) { return webview != null && ((webview.getContentHeight() * webview.getScale() - (webview.getHeight() + webview.getScrollY())) <= 2 * mTouchSlop); } public static boolean isViewGroupToBottom(ViewGroup viewGroup) { View subChildView = viewGroup.getChildAt(0); return (subChildView != null && subChildView.getMeasuredHeight() <= viewGroup.getScrollY() + viewGroup.getHeight()); } public static boolean isScrollViewToBottom(ScrollView scrollView) { if (scrollView != null) { int scrollContentHeight = scrollView.getScrollY() + scrollView.getMeasuredHeight() - scrollView.getPaddingTop() - scrollView.getPaddingBottom(); int realContentHeight = scrollView.getChildAt(0).getMeasuredHeight(); if (scrollContentHeight == realContentHeight) { return true; } } return false; } public static boolean isAbsListViewToBottom(AbsListView absListView) { if (absListView != null && absListView.getAdapter() != null && absListView.getChildCount() > 0 && absListView.getLastVisiblePosition() == absListView.getAdapter().getCount() - 1) { View lastChild = absListView.getChildAt(absListView.getChildCount() - 1); return lastChild.getBottom() <= absListView.getMeasuredHeight(); } return false; } public static boolean isRecyclerViewToBottom(RecyclerView recyclerView) { if (recyclerView != null) { RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager == null || manager.getItemCount() == 0) { return false; } if (manager instanceof LinearLayoutManager) { // 处理item高度超过一屏幕时的情况 View lastVisibleChild = recyclerView.getChildAt(recyclerView.getChildCount() - 1); if (lastVisibleChild != null && lastVisibleChild.getMeasuredHeight() >= recyclerView.getMeasuredHeight()) { if (android.os.Build.VERSION.SDK_INT < 14) { return !(ViewCompat.canScrollVertically(recyclerView, 1) || recyclerView.getScrollY() < 0); } else { return !ViewCompat.canScrollVertically(recyclerView, 1); } } LinearLayoutManager layoutManager = (LinearLayoutManager) manager; if (layoutManager.findLastCompletelyVisibleItemPosition() == layoutManager.getItemCount() - 1) { return true; } } else if (manager instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) manager; int[] out = layoutManager.findLastCompletelyVisibleItemPositions(null); int lastPosition = layoutManager.getItemCount() - 1; for (int position : out) { if (position == lastPosition) { return true; } } } } return false; } public static void scrollAViewBy(View view, int height) { if (view instanceof RecyclerView) ((RecyclerView) view).scrollBy(0, height); else if (view instanceof ScrollView) ((ScrollView) view).smoothScrollBy(0, height); else if (view instanceof AbsListView) ((AbsListView) view).smoothScrollBy(height, 0); else { try { Method method = view.getClass().getDeclaredMethod("smoothScrollBy", Integer.class, Integer.class); method.invoke(view, 0, height); } catch (Exception e) { view.scrollBy(0, height); } } } public static void scrollToBottom(final ScrollView scrollView) { if (scrollView != null) { scrollView.post(new Runnable() { @Override public void run() { scrollView.fullScroll(ScrollView.FOCUS_DOWN); } }); } } public static void scrollToBottom(final AbsListView absListView) { if (absListView != null) { if (absListView.getAdapter() != null && absListView.getAdapter().getCount() > 0) { absListView.post(new Runnable() { @Override public void run() { absListView.setSelection(absListView.getAdapter().getCount() - 1); } }); } } } public static void scrollToBottom(final RecyclerView recyclerView) { if (recyclerView != null) { if (recyclerView.getAdapter() != null && recyclerView.getAdapter().getItemCount() > 0) { recyclerView.post(new Runnable() { @Override public void run() { recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount() - 1); } }); } } } public static void scrollToBottom(View view) { if (view instanceof RecyclerView) scrollToBottom((RecyclerView) view); if (view instanceof AbsListView) scrollToBottom((AbsListView) view); if (view instanceof ScrollView) scrollToBottom((ScrollView) view); } public static int getScreenHeight(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(dm); return dm.heightPixels; } }