ViewDragHelper实现RecyclerView下拉刷新和上拉加载更多的类似效果

这篇博客介绍了如何利用ViewDragHelper在Android中实现类似RecyclerView下拉刷新和上拉加载更多的滑动手势效果。通过自定义ViewGroup PullSlideParent,结合onInterceptTouchEvent和onTouchEvent方法,监听和处理滑动事件。同时,文章还涵盖了布局测量、触摸事件拦截以及回调接口的设计,以支持上拉和下拉操作。
摘要由CSDN通过智能技术生成

private static final float SWIPE_BACK_FACTOR = 0.9f;
private float swipeBackFraction;

public PullSlideParent(Context context) {
this(context, null);
}

public PullSlideParent(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public PullSlideParent(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mDragHelper = ViewDragHelper.create(this, new PullSlideParent.DragHelperCallback());
mHeader = (ViewGroup) LayoutInflater.from(getContext()).inflate(R.layout.pull_side_header, this, false);
mFooter = (ViewGroup) LayoutInflater.from(getContext()).inflate(R.layout.pull_side_footer, this, false);
addView(mHeader);
addView(mFooter);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
if (childCount != 3) {
throw new IllegalStateException(“PullSlideParent must contains only three direct child.”);
}

measureChildren(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (getChildCount() != 3) {
return;
}

mHeaderMeasuredHeight = mHeader.getMeasuredHeight();
mFooterMeasuredHeight = mFooter.getMeasuredHeight();
mHeader.layout(0, -mHeaderMeasuredHeight, getMeasuredWidth(), 0);
mFooter.layout(0, getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight() + mFooterMeasuredHeight);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child instanceof RecyclerView) {
mDragContentView = child;
mDragContentView.layout(0, 0, mDragContentView.getMeasuredWidth(), mDragContentView.getMeasuredHeight());
}
}
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = ev.getY();
deltaY = 0;
mDragHelper.shouldInterceptTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
deltaY = ev.getY() - lastY;
lastY = ev.getY();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragHelper.shouldInterceptTouchEvent(ev);
deltaY = 0;
break;
default:
}
if (canDown && deltaY > 0 && !mDragContentView.canScrollVertically(-1)) {
return mDragHelper.shouldInterceptTo

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

uchEvent(ev);
}

if (canUp && deltaY < 0 && !mDragContentView.canScrollVertically(1)) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}

@Override
public void computeScroll() {
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}

public void setCanUp(boolean canUp) {
this.canUp = canUp;
}

public void setCanDown(boolean canDown) {
this.canDown = canDown;
}

public void setOnPullListener(PullSlideParent.OnPullListener onPullListener) {
this.onPullListener = onPullListener;
}

public interface OnPullListener {
void onPullUp();

void onPullDown();
}

private class DragHelperCallback extends ViewDragHelper.Callback {

@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return child == mDragContentView;
}

@Override
public int getViewVerticalDragRange(@NonNull View child) {
return Math.max(mHeaderMeasuredHeight, mFooterMeasuredHeight);
}

@Override
public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
if (top > 0) {
swipeBackFraction = 1.0f * top / mHeaderMeasuredHeight;
mHeader.setTranslationY(top);
} else if (top < 0) {
swipeBackFraction = -1.0f * top / mFooterMeasuredHeight;
mFooter.setTranslationY(top);
} else {
swipeBackFraction = 0f;
down = false;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值