大家都知道android-Ultra-Pull-To-Refresh是一個功能很強大的下拉刷新框架。
項目地址:https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
原理剖析文檔:android-Ultra-Pull-to-Refresh
Demo地址:https://raw.githubusercontent.com/liaohuqiu/android-Ultra-Pull-To-Refresh/master/ptr-demo.apk
相信正常的使用都沒什么問題碟摆,但是有些點還是要注意的预厌。
1、自定義下拉頭部的幾個方法的調(diào)用時機:
/**
* 重置 View 攻谁,隱藏忙碌進度條稚伍,隱藏箭頭 View ,更新最后刷新時間戚宦。
* Content 重新回到頂部个曙, Header 消失,整個下拉刷新過程完全結(jié)束以后受楼,重置 View 垦搬。
*/
@Override
public void onUIReset(PtrFrameLayout ptrFrameLayout) {
}
/**
* 準備刷新,隱藏忙碌進度條艳汽,顯示箭頭 View 猴贰,顯示文字,如果是下拉刷新骚灸,顯示“下拉刷新”糟趾,如果是釋放刷新,顯示“下拉”。
* 準備刷新义郑,Header 將要出現(xiàn)時調(diào)用蝶柿。
*/
@Override
public void onUIRefreshPrepare(PtrFrameLayout ptrFrameLayout) {
}
/**
* 開始刷新,Header 進入刷新狀態(tài)之前調(diào)用非驮。
* 開始刷新交汤,隱藏箭頭 View ,顯示忙碌進度條劫笙,顯示文字芙扎,顯示“加載中...”,更新最后刷新時間填大。
*/
@Override
public void onUIRefreshBegin(PtrFrameLayout ptrFrameLayout) {
}
/**
* 刷新結(jié)束戒洼,隱藏箭頭 View ,隱藏忙碌進度條允华,顯示文字圈浇,顯示“更新完成”,寫入最后刷新時間靴寂。
* 刷新結(jié)束磷蜀,Header 開始向上移動之前調(diào)用。
*/
@Override
public void onUIRefreshComplete(PtrFrameLayout ptrFrameLayout) {
}
/**
* 下拉過程中位置變化回調(diào)百炬。
* <p>
* 在拖動情況下褐隆,當下拉距離從 小于刷新高度到大于刷新高度 時,箭頭 View 從向下剖踊,變成向上庶弃,同時改變文字顯示。
* 當下拉距離從 大于刷新高度到小于刷新高度 時蜜宪,箭頭 View 從向上虫埂,變?yōu)橄蛳拢瑫r改變文字顯示圃验。
*/
@Override
public void onUIPositionChange(PtrFrameLayout ptrFrameLayout, boolean b, byte b1, PtrIndicator ptrIndicator) {
float percent = Math.min(1f, ptrIndicator.getCurrentPercent());
}
然后在自定義頭部的時候最好把布局也順便寫進去,這樣使用起來就比較方便一點:
public class CommonPtrHeader extends FrameLayout implements PtrUIHandler{
private View headerView;
private ProgressBar mProgressBar;
public CommonPtrHeader(Context context) {
super(context);
init();
}
public CommonPtrHeader(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
headerView = LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_head, this);
mProgressBar = (ProgressBar) headerView.findViewById(R.id.pull_to_refresh_progress);
}
}
2缝呕、當下拉刷新中有 ViewPager 時澳窑,比如 ListView 上面加個 Banner 廣告條,這時候其實是會有滑動沖突的供常,那么網(wǎng)上搜很多都說要重寫 ViewPager 或者 PtrFrameLayout摊聋,而且大部分都是達不到效果的,其實細心的你可能會發(fā)現(xiàn)栈暇,PtrFrameLayout 已經(jīng)提供好方法來解決這一問題了麻裁,只是我們平時比較容易忽略:
好了,只需要這樣就能解決沖突了:
ptrFrame.disableWhenHorizontalMove(true);
-----------------------------分割線(補充)-------------------------------------------------------
上面說的設(shè)置 disableWhenHorizontalMove ,大家是不是發(fā)現(xiàn)好像沒什么用煎源,是的色迂,下面在網(wǎng)上找了個方法,使用中順利解決了沖突問題手销,而且好像還沒發(fā)現(xiàn)什么問題歇僧,需要重寫一下 PtrClassicFrameLayout ,下面是代碼:
public class FixPtrFrameLayout extends PtrClassicFrameLayout {
private float startY;
private float startX;
// 記錄viewPager是否拖拽的標記
private boolean mIsHorizontalMove;
// 記錄事件是否已被分發(fā)
private boolean isDeal;
private ViewPager mViewPager;
private int mTouchSlop;
public FixPtrFrameLayout(Context context) {
super(context);
}
public FixPtrFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixPtrFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* PtrHTFrameLayout has a viewpager
*
* @param viewPager
*/
public void setViewPager(ViewPager viewPager) {
this.mViewPager = viewPager;
if (mViewPager == null) {
throw new IllegalArgumentException("viewPager can not be null");
}
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mViewPager == null) {
return super.dispatchTouchEvent(ev);
}
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 記錄手指按下的位置
startY = ev.getY();
startX = ev.getX();
// 初始化標記
mIsHorizontalMove = false;
isDeal = false;
break;
case MotionEvent.ACTION_MOVE:
// 如果已經(jīng)判斷出是否由橫向還是縱向處理锋拖,則跳出
if (isDeal) {
break;
}
/**攔截禁止交給Ptr的 dispatchTouchEvent處理**/
mIsHorizontalMove = true;
// 獲取當前手指位置
float endY = ev.getY();
float endX = ev.getX();
float distanceX = Math.abs(endX - startX);
float distanceY = Math.abs(endY - startY);
if (distanceX != distanceY) {
// 如果X軸位移大于Y軸位移诈悍,那么將事件交給viewPager處理。
if (distanceX > mTouchSlop && distanceX > distanceY) {
mIsHorizontalMove = true;
isDeal = true;
} else if (distanceY > mTouchSlop) {
mIsHorizontalMove = false;
isDeal = true;
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//下拉刷新狀態(tài)時如果滾動了viewpager 此時mIsHorizontalMove為true 會導(dǎo)致PtrFrameLayout無法恢復(fù)原位
// 初始化標記,
mIsHorizontalMove = false;
isDeal = false;
break;
}
if (mIsHorizontalMove) {
return dispatchTouchEventSupper(ev);
}
return super.dispatchTouchEvent(ev);
}
}
使用方法就是通過里面的 setViewPager 方法將你的 banner里面的 viewpager 賦值進去就好兽埃,如果你的 banne r是寫在 adapter 里面的侥钳,那你可以將 FixPtrFrameLayout 的實例賦值進去 adapter 里面,再設(shè)置 viewpager 就行柄错。