PullToRefreshListview 下拉刷新控件本身有一個問題,就是當使用 setSelection 后,第一次滑動會卡住,后面再次滑動就沒有問題了。而需求就是,我們需要在 PullToRefreshListview 上浮動一個菜單,滑倒頂部的時候,header 里面的菜單顯示,浮動的菜單隱藏,等上拉至 header 里面的菜單隱藏后,浮動的菜單就顯示出來。
因為第一次滑動會卡頓,所以我們可以用代碼模擬一個細微的肉眼無法察覺的滑動,這樣我們再次滑動的時候就沒有問題,核心代碼如下:
if(mFloatingFilterView.getVisibility() == View.VISIBLE) {
ptrlv.getRefreshableView().setSelection(1);
// ptrlv.getRefreshableView().smoothScrollToPosition(1);
UIUtil.postDelayed(new Runnable() {
@Override
public void run() {
CommonUtil.analogUserScroll(ptrlv, 0x01, ScreenUtil.getDeviceWidth() / 2, ScreenUtil.getDeviceHeight() / 2, ScreenUtil.getDeviceWidth() / 2, ScreenUtil.getDeviceHeight());
}
}, 100);
}
/**
* 模擬用戶滑動操作
*
* @param view 要觸發操作的view
* @param type 模擬操作類型:均勻滑動、快速滑動
* @param p1x 滑動的起始點x坐標
* @param p1y 滑動的起始點y坐標
* @param p2x 滑動的終點x坐標
* @param p2y 滑動的終點y坐標
*/
public static void analogUserScroll(View view, final int type, final float p1x, final float p1y, final float p2x, final float p2y) {
if (view == null) {
return;
}
long downTime = SystemClock.uptimeMillis();//模擬按下去的時間
long eventTime = downTime;
float pX = p1x;
float pY = p1y;
int speed = 0;//快速滑動
float touchTime = 116;//模擬滑動時發生的觸摸事件次數
//平均每次事件要移動的距離
float perX = (p2x - p1x) / touchTime;
float perY = (p2y - p1y) / touchTime;
boolean isReversal = perX < 0 || perY < 0;//判斷是否反向:手指從下往上滑動,或者手指從右往左滑動
boolean isHandY = Math.abs(perY) > Math.abs(perX);//判斷是左右滑動還是上下滑動
if (type == USER_TOUCH_TYPE_1) {//加速滑動
touchTime = 10;//如果是快速滑動,則發生的觸摸事件比均勻滑動更少
speed = isReversal ? -20 : 20;//反向移動則坐標每次遞減
}
//模擬用戶按下
MotionEvent downEvent = MotionEvent.obtain(downTime, eventTime,
ACTION_DOWN, pX, pY, 0);
view.dispatchTouchEvent(downEvent);
//模擬移動過程中的事件
List<MotionEvent> moveEvents = new ArrayList<>();
boolean isSkip = false;
for (int i = 0; i < touchTime; i++) {
pX += (perX + speed);
pY += (perY + speed);
if ((isReversal && pX < p2x) || (!isReversal && pX > p2x)) {
pX = p2x;
isSkip = !isHandY;
}
if ((isReversal && pY < p2y) || (!isReversal && pY > p2y)) {
pY = p2y;
isSkip = isHandY;
}
eventTime += 20.0f;//事件發生的時間要不斷遞增
MotionEvent moveEvent = getMoveEvent(downTime, eventTime, pX, pY);
moveEvents.add(moveEvent);
view.dispatchTouchEvent(moveEvent);
if (type == USER_TOUCH_TYPE_1) {//加速滑動
speed += (isReversal ? -70 : 70);
}
if (isSkip) {
break;
}
}
//模擬手指離開屏幕
MotionEvent upEvent = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_UP, pX, pY, 0);
view.dispatchTouchEvent(upEvent);
//回收觸摸事件
downEvent.recycle();
for (int i = 0; i < moveEvents.size(); i++) {
moveEvents.get(i).recycle();
}
upEvent.recycle();
}
private static MotionEvent getMoveEvent(long downTime, long eventTime, float pX, float pY) {
return MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_MOVE, pX, pY, 0);
}