码云链接,欢迎clone
史上最全recycleView 集合,下拉刷新+上拉加载+左滑删除+点击按钮滑动到指定位置
最近项目需求,需要使用viewpager+fragment,同时还有类似支付宝的滑动到指定位置需求,另外还有点击顶部button,使recycleView滑动到指定位置,简直是把我这个老黄牛给累死了,好在万能的百度,给了我指引。于是我这个搬砖工,把网上现在的东西组合了下,有了今天的成果。话不多说,上效果图
主要思路
- 使用viewpager+tablelqyout,这个没啥好说的,现在比较流行的多页面框架
- 下拉刷新,上拉加载,这个使用了git上非常著名的smartRefreshLayout,不过话说回来,自从用了这个框架,一句话:谁用谁知道!
- 左滑菜单,这个网上实现的也非常多,但是很可惜,像easySwipterLayout,还有其它的一些实现方式都是在recycleView上实现,这样造成了与recycleView代码混合在一起,非常不利于现在的少侵入式框架,最终发现有一个WeSwipe,可以实现与recycleView的最少侵入。于是就选择了这款左滑框架。
关键代码
- recycleView设置关键代码 ,其中有上拉刷新,下拉加载,还有滑动的监听,在滑动监听中找到当前屏幕可见的第一条item的position,其中下面的代码 是关键
LinearLayoutManager ll = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstItem = ll.findFirstVisibleItemPosition();
//下拉刷新设置
refreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
refreshLayout.finishRefresh(2000);
}
});
//上拉加载设置
refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
refreshLayout.finishLoadMore(2000);
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
mAdapter.setDelectedItemListener(new WorkAdapter.DeletedItemListener() {
@Override
public void deleted(int position) {
dataList.remove(position);
mAdapter.notifyItemRemoved(position);
}
});
recyclerView.setAdapter(mAdapter);
WeSwipe.attach(recyclerView);
// recycleView滚动需要的类
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (mShouldScroll && RecyclerView.SCROLL_STATE_IDLE == newState) {
mShouldScroll = false;
smoothMoveToPosition(recyclerView, mToPosition);
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//滑动终止
settabbarTop();
}
}
});
/**
* 滑动到指定位置
*/
private void smoothMoveToPosition(RecyclerView mRecyclerView, final int position) {
// 第一个可见位置
int firstItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(0));
// 最后一个可见位置
int lastItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1));
if (position < firstItem) {
// 第一种可能:跳转位置在第一个可见位置之前,使用smoothScrollToPosition
mRecyclerView.smoothScrollToPosition(position);
} else if (position <= lastItem) {
// 第二种可能:跳转位置在第一个可见位置之后,最后一个可见项之前
int movePosition = position - firstItem;
if (movePosition >= 0 && movePosition < mRecyclerView.getChildCount()) {
int top = mRecyclerView.getChildAt(movePosition).getTop();
// smoothScrollToPosition 不会有效果,此时调用smoothScrollBy来滑动到指定位置
mRecyclerView.smoothScrollBy(0, top);
}
} else {
// 第三种可能:跳转位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
// 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法
mRecyclerView.smoothScrollToPosition(position);
mToPosition = position;
mShouldScroll = true;
}
}
adapter关键代码,使用weSwip左滑菜单 ,必须实现WeSwipeHelper.SwipeLayoutTypeCallBack,这里有三个关键方法
解释如下:
- getSwipeWidth 方法是指定可左滑动的距离
- needSwipeLayout 方法是右滑的菜单view
- onScreenView 返回的是contentView,即全屏的view
@Override
public float getSwipeWidth() {
//布局隐藏超过父布局的范围的时候这里得不到宽度
return dip2px(context, 240);
}
@Override
public View needSwipeLayout() {
return slideItem;
}
@Override
public View onScreenView() {
return textView;
}
package cn.ttxs.wq.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import cn.ttxs.wq.R;
import cn.we.swipe.helper.WeSwipeHelper;
/**
* Created by WANG on 18/4/24.
*/
public class WorkAdapter extends RecyclerView.Adapter<WorkAdapter.RecViewholder> {
private Context context;
private List<String> dataList = new ArrayList<>();
private LayoutInflater layoutInflater;
DeletedItemListener delectedItemListener;
public void setDelectedItemListener(DeletedItemListener deletedItemListener) {
this.delectedItemListener = deletedItemListener;
}
public WorkAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
layoutInflater = LayoutInflater.from(context);
}
public void setList(List<String> list) {
dataList.clear();
dataList.addAll(list);
notifyItemMoved(0, dataList.size() - 1);
}
public List<String> getDataList() {
return dataList;
}
public void removeDataByPosition(int position) {
if (position >= 0 && position < dataList.size()) {
dataList.remove(position);
notifyItemRemoved(position);
}
}
@Override
public RecViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.layout_item_twotype, parent, false);
return new RecViewholder(view);
}
@Override
public void onBindViewHolder(final RecViewholder holder, int position) {
holder.textView.setText(dataList.get(holder.getAdapterPosition()));
holder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "s " + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.zhiding.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "置顶" + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.yidu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "已读" + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.shanchu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != delectedItemListener) {
delectedItemListener.deleted(holder.getAdapterPosition());
}
}
});
}
@Override
public int getItemCount() {
return dataList.size();
}
/**
* view.getWidth()获取的是屏幕中可以看到的大小.
*/
public class RecViewholder extends RecyclerView.ViewHolder implements WeSwipeHelper.SwipeLayoutTypeCallBack {
public TextView textView;
public LinearLayout slide;
public TextView zhiding, yidu, shanchu;
public RelativeLayout slideItem;
public RecViewholder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.item_text);
zhiding = itemView.findViewById(R.id.tv_totop);
yidu = itemView.findViewById(R.id.tv_read);
shanchu = itemView.findViewById(R.id.tv_del);
slide = itemView.findViewById(R.id.slide);
slideItem = itemView.findViewById(R.id.slide_itemView);
}
@Override
public float getSwipeWidth() {
//布局隐藏超过父布局的范围的时候这里得不到宽度
return dip2px(context, 240);
}
@Override
public View needSwipeLayout() {
return slideItem;
}
@Override
public View onScreenView() {
return textView;
}
}
/**
* 根据手机分辨率从DP转成PX
*
* @param context
* @param dpValue
* @return
*/
public static int dip2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public interface DeletedItemListener {
void deleted(int position);
}
}
recycleView使用的layout文件关键代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="1dp"
android:clipChildren="false">
<RelativeLayout
android:id="@+id/slide_itemView"
android:clipChildren="false"
android:tag="slide_flag"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#e1e1e1"
android:gravity="center"
android:text="item"
android:textColor="#333333"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/slide"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/item_text"
android:clipChildren="false"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_totop"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="#C8C7CD"
android:gravity="center"
android:text="置顶"
android:textColor="#ffffff" />
<TextView
android:id="@+id/tv_read"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="#FF9D00"
android:gravity="center"
android:text="设为已读"
android:textColor="#ffffff" />
<TextView
android:id="@+id/tv_del"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="#FE3C31"
android:gravity="center"
android:text="删除"
android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>