Android ListView 下拉重新整理,上拉載入更多,帶動畫 自定義控制元件
阿新 • • 發佈:2019-01-02
之前每次 專案中用到ListView 的 下拉重新整理 以及上拉分頁載入 都是 用的 網上 下載 的 類庫,
使用起來 諸多不便 ,於是 趁著有空 ,自己封裝了ListView 讓其 實現 下拉重新整理,以及分頁載入功能。
以下是 效果圖:
當 滑動到 ListView 頂部 或 尾部 時,再次手指上拉或下拉 則會 觸發 ListView 的 重新整理 ,並 顯示 重新整理 動畫,完成後動畫會 緩慢消失。
Demo 下載 地址:點選開啟連結
具體 實現原理:
首先對 ListView 要設定 OnScrollListener 監聽 其 滑動 狀態 ,並 記錄此 狀態。
ListView的 滑動 狀態 有 三種
靜止狀態,SCROLL_STATE_IDLE 手指滾動狀態,SCROLL_STATE_TOUCH_SCROLL 手指不動了,但是螢幕還在滾動狀態。SCROLL_STATE_FLING
上下拉重新整理 時 ListView的 滾動狀態 必須為 手指滾動才觸發重新整理。
還要 對 ListView 設定 觸控 監聽。
判斷 ListView 的 滑動 方向,計算其 手指拖動距離,以及手指擡起時的 重新整理動畫的 狀態
以下是 ListView 的 觸控 和 滾動 監聽 程式碼
首先 在 滾動 監聽 了 記錄 當前 的 滾動狀態。
然後 在 觸控監聽裡 當狀態 為 Action.Move 移動 時,判斷滾動的 方向,以及 ListView 當前位置 處於頂部還是底部,並且 是否正在重新整理。
然後 根據 手指 移動的 距離 除以相應倍數 ,讓 重新整理動畫 控制元件 緩慢 出現。 在Action.Up 中 判斷 當前的 重新整理控制元件 顯示 的 高度 是否 觸發 重新整理 方法。
int currentScorllState; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { currentScorllState = scrollState; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } boolean rememberFreshYTag = true; float freshY; float tempY; int times = 3; boolean downTag = false; float y; @Override public boolean onTouch(View view, MotionEvent motionEvent) { y = motionEvent.getY(); switch (motionEvent.getAction()) { case MotionEvent.ACTION_MOVE: float scrollHeight = y - tempY; if (scrollHeight > 0) { downTag = true; } else { downTag = false; } if (currentScorllState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL && this.getFirstVisiblePosition() == 0 && this.getTop() == 0 && downTag && !freshingTag ) { topFreshTag = true; if (rememberFreshYTag) { freshY = y; } rememberFreshYTag = false; float min = Math.min(headHeight + headHeight / 2, (y - freshY) / times); imageViewHead.setPadding(0, (int) (-headHeight + min), 0, 0); Log.i("testss", "topFresh" + y); } else if (currentScorllState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL && this.getLastVisiblePosition() == getCount() - 1 && this.getBottom() == this.getHeight() && !downTag && !freshingTag ) { bottomFreshTag = true; if (rememberFreshYTag) { freshY = y; } rememberFreshYTag = false; float min = Math.min(footHeight + footHeight / 2, -(y - freshY)); imageViewFoot.setPadding(0, 0, 0, (int) (-footHeight + min)); Log.i("testss", "buttomFresh" + y + "---" + freshY); } break; case MotionEvent.ACTION_UP: if (topFreshTag && !freshingTag) { Log.i("testss", "uptopFreshTag"); // 手指 擡起時 符合 條件 則 觸發 頂部重新整理 judgeToFresh(TOP_FRESH, imageViewHead, headHeight); } if (bottomFreshTag && !freshingTag) { // Log.i("testss", "upbottomFreshTag"); // 手指 擡起時 符合 條件 則 觸發 底部重新整理 judgeToFresh(BOTTOM_FRESH, imageViewFoot, footHeight); } break; } tempY = y; return super.onTouchEvent(motionEvent); }
以下 是判斷 是否 重新整理的方法
/**
* 判斷 是否 觸發 重新整理
*
* @param freshType 重新整理 的型別 頂部重新整理 或 底部重新整理
* @param imageView 重新整理動畫 的 控制元件
* @param height 當前 重新整理動畫 控制元件 顯示 的 高度
*/
private void judgeToFresh(int freshType, ImageView imageView, int height) {
int paddingHeight = freshType == TOP_FRESH ? imageView.getPaddingTop() : imageView.getPaddingBottom();
if (paddingHeight == height / 2) {
imageView.setPadding(0, 0, 0, 0);
freshingTag = true;
if (freshType == TOP_FRESH) {
onTopFresh();
} else {
onBottomFresh();
}
} else {
dissHeadOrFootView(imageView, freshType, -paddingHeight, height);
}
}
/**
* 開始 頂部 重新整理
*/
private void onTopFresh() {
// 開啟 動畫
startOrStopAnimation(imageViewHead, true);
/**
* 如果 設定 了外部 監聽
* 則 呼叫 外部監聽 的 重新整理 方法
* 否則 過1s後 自動完成 重新整理動畫
*/
if (onListViewFreshListener == null) {
tempHandler.sendEmptyMessageDelayed(TOP_FRESH, 1000);
} else {
onListViewFreshListener.onTopFreshing();
}
}
/**
* 開始 底部 重新整理
*/
private void onBottomFresh() {
// 開啟 動畫
startOrStopAnimation(imageViewFoot, true);
/**
* 如果 設定 了外部 監聽
* 則 呼叫 外部監聽 的 重新整理 方法
* 否則 過1s後 自動完成 重新整理動畫
*/
if (onListViewFreshListener == null) {
tempHandler.sendEmptyMessageDelayed(BOTTOM_FRESH, 1000);
} else {
onListViewFreshListener.onBottomFreshing();
}
}
Demo 下載 地址:點選開啟連結