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

private final ViewGroup mHeader;
private final ViewGroup mFooter;
private int mHeaderMeasuredHeight;
private int mFooterMeasuredHeight;

private View mDragContentView;
private float lastY;
private float deltaY;
private OnPullListener onPullListener;
private boolean up = false; //上拉
private boolean down = false; //下拉
private boolean canUp = true;
private boolean canDown = true;

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.shouldInterceptTouchEvent(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

最后

题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

Android开发8年,阿里、百度一面惨被吊打!我是否应该转行了?

【Android进阶学习视频】、【全套Android面试秘籍】

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
oid面试秘籍】**

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例代码: 首先,在XML布局文件中添加一个RecyclerView和SwipeRefreshLayout控件: ```xml <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> ``` 然后,在Activity或Fragment中初始化RecyclerView和SwipeRefreshLayout,并设置相应的监听器: ```java // 初始化RecyclerView和SwipeRefreshLayout mRecyclerView = findViewById(R.id.recycler_view); mSwipeRefreshLayout = findViewById(R.id.swipe_refresh_layout); // 设置布局管理器和适配器 mLayoutManager = new LinearLayoutManager(this); mAdapter = new MyAdapter(mDataList); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(mAdapter); // 设置下拉刷新监听器 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 进行下拉刷新操作 refreshData(); } }); // 设置上加载多监听器 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE && isSlideToBottom(recyclerView)) { // 滑动到底部,触发加载多操作 loadMoreData(); } } }); // 判断RecyclerView是否滑动到底部 private boolean isSlideToBottom(RecyclerView recyclerView) { LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); int itemCount = layoutManager.getItemCount(); return lastVisibleItemPosition == (itemCount - 1); } // 进行下拉刷新操作 private void refreshData() { // 在这里进行刷新数据的操作 // 刷新完成后调用mSwipeRefreshLayout.setRefreshing(false)停止刷新动画 } // 进行上加载多操作 private void loadMoreData() { // 在这里进行加载多数据的操作 // 加载完成后调用mAdapter.notifyDataSetChanged()新列表 } ``` 需要注意的是,上述代码中的MyAdapter是自定义的RecyclerView适配器,需要根据实际情况进行修改。另外,刷新和加载多操作需要在子线程中进行,可以使用AsyncTask等方式进行异步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值