Android ScrollView監聽滑動到頂部和底部的兩種方式
阿新 • • 發佈:2019-02-02
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;
}
}