1. 程式人生 > >Android ScrollView監聽滑動到頂部和底部的兩種方式

Android ScrollView監聽滑動到頂部和底部的兩種方式

import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; /** * 監聽ScrollView滾動到頂部或者底部做相關事件攔截 */ public class SmartScrollView extends ScrollView { private boolean isScrolledToTop = true;  // 初始化的時候設定一下值 private boolean isScrolledToBottom = false;
public ScanScrollView(Context context, AttributeSet attrs) { super(context, attrs); } private ISmartScrollChangedListener mSmartScrollChangedListener; /** 定義監聽介面 */ public interface ISmartScrollChangedListener { void onScrolledToBottom(); void onScrolledToTop(); }
public void setScanScrollChangedListener(ISmartScrollChangedListener smartScrollChangedListener) { mSmartScrollChangedListener = smartScrollChangedListener; } @Override protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
if (scrollY == 0) { isScrolledToTop = clampedY; isScrolledToBottom = false; } else { isScrolledToTop = false; isScrolledToBottom = clampedY; } notifyScrollChangedListeners(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (android.os.Build.VERSION.SDK_INT < 9) { // API 9及之後走onOverScrolled方法監聽 if (getScrollY() == 0) { // 小心踩坑1: 這裡不能是getScrollY() <= 0 isScrolledToTop = true; isScrolledToBottom = false; } else if (getScrollY() + getHeight() - getPaddingTop()-getPaddingBottom() == getChildAt(0).getHeight()) { // 小心踩坑2: 這裡不能是 >=          // 小心踩坑3(可能忽視的細節2):這裡最容易忽視的就是ScrollView上下的padding  isScrolledToBottom = true; isScrolledToTop = false; } else { isScrolledToTop = false; isScrolledToBottom = false; } notifyScrollChangedListeners(); } // 有時候寫程式碼習慣了,為了相容一些邊界奇葩情況,上面的程式碼就會寫成<=,>=的情況,結果就出bug了 // 我寫的時候寫成這樣:getScrollY() + getHeight() >= getChildAt(0).getHeight() // 結果發現快滑動到底部但是還沒到時,會發現上面的條件成立了,導致判斷錯誤 // 原因:getScrollY()值不是絕對靠譜的,它會超過邊界值,但是它自己會恢復正確,導致上面的計算條件不成立 // 仔細想想也感覺想得通,系統的ScrollView在處理滾動的時候動態計算那個scrollY的時候也會出現超過邊界再修正的情況 } private void notifyScrollChangedListeners() { if (isScrolledToTop) { if (mSmartScrollChangedListener != null) { mSmartScrollChangedListener.onScrolledToTop(); } } else if (isScrolledToBottom) { if (mSmartScrollChangedListener != null) { mSmartScrollChangedListener.onScrolledToBottom(); } } } public boolean isScrolledToTop() { return isScrolledToTop; } public boolean isScrolledToBottom() { return isScrolledToBottom; } }