上拉刷新和下拉刷新的实现

article/2025/10/26 17:56:25

先来两张效果图

         

关于下拉刷新,Google提供了一个布局SwipRefreshLayout,它里面可以包涵一个滑动控件,然后你可以设置它的刷新事件就OK了,非常简单用。但是上拉刷新就有点麻烦了。网上很多方法都是给recyclerview添加footer的方法,我也采用这种方法实现了一个。其实也就是recyclerview的item多布局。一般布局和footer布局。,在上滑到最后一个item的时候,就把加一个footer类型的item,这里,然后很明显这里也就行滑动监听,就监听它上滑动到最后一个item。下面先。下面直接给代码

。导入依赖。由于wish我是用了用OKhttp就是实现的联网刷新,所以导入了OKhttp的依赖包,当然还得加联网权限。

 compile 'com.android.support:recyclerview-v7:25.3.1'compile 'com.squareup.okhttp:okhttp:2.4.0'
贴个footer的布局,因为footer包含两个部分“正在加载:”,和没有“没有更多了,”。用用的时候根据情况选择隐藏、显示或者gone
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:id="@+id/line1"android:layout_width="match_parent"android:layout_height="60dp"android:gravity="center"><ProgressBarandroid:layout_width="40dp"android:layout_height="40dp"/><TextViewandroid:layout_width="wrap_content"android:layout_height="50dp"android:gravity="center_vertical"android:layout_marginLeft="5dp"android:text="正在加载..."android:textSize="20dp"/></LinearLayout><LinearLayoutandroid:id="@+id/line2"android:layout_width="match_parent"android:layout_height="60dp"android:gravity="center"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="没有更多了!"android:textSize="20sp"/></LinearLayout></LinearLayout>

最核心的两个类adapter和监听。
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{private ArrayList<String> list;private final int ITEM=0;//加载的为一般itemprivate final int FOOT=1;//加载footer//上拉加载的状态private int loadstate=2;//默认加载完成public final int LOADING = 1;//正在加载public final int FINISH = 2;// 加载完成public final int END = 3;  //没有更多数据了(显示另一footer)public MyAdapter(ArrayList<String> list) {this.list = list;}public void setLoadstate(int loadstate) {//用于动态设置加载状态this.loadstate = loadstate;notifyDataSetChanged();}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//通过加载类型,来显示不同的view。viewType由getItemViewType确定if (viewType == ITEM) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);return new ItemViewHodler(view);} else if (viewType == FOOT) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.foot, parent, false);return new FootViewHodler(view);}return null;}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {//绑定viewholder的时候根据类型来绑定if (holder instanceof ItemViewHodler) {ItemViewHodler itemhodler= (ItemViewHodler) holder;itemhodler.textView.setText(list.get(position));} else if (holder instanceof FootViewHodler) {FootViewHodler foothoder = (FootViewHodler) holder;switch (loadstate){case LOADING:foothoder.line1.setVisibility(View.VISIBLE);foothoder.line2.setVisibility(View.GONE);break;case FINISH://设置成INVISIBLE而不是gone,为了给footer预留位置,美观foothoder.line1.setVisibility(View.INVISIBLE);foothoder.line2.setVisibility(View.GONE);break;case END:foothoder.line1.setVisibility(View.GONE);foothoder.line2.setVisibility(View.VISIBLE);break;}}}@Overridepublic int getItemViewType(int position) {//最后一个加载footer,if (position + 1 == getItemCount()) {return FOOT;} else {return ITEM;}}@Overridepublic int getItemCount() {return list.size()+1;//因为要加上一个footer}private class ItemViewHodler extends RecyclerView.ViewHolder{TextView textView;public ItemViewHodler(View itemView) {super(itemView);textView= (TextView) itemView.findViewById(R.id.text);}}private class FootViewHodler extends RecyclerView.ViewHolder{LinearLayout line1;LinearLayout line2;public FootViewHodler(View itemView) {super(itemView);line1= (LinearLayout) itemView.findViewById(R.id.line1);line2= (LinearLayout) itemView.findViewById(R.id.line2);}}
}

public abstract class FootScrollListener extends RecyclerView.OnScrollListener {//通过重写RecyclerView的滑动监听来判断是否滑动到底部private boolean isScrollUp=false;@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);/*newState表示当前滑动的状态SCROLL_STATE_IDLE:不滑动SCROLL_STATE_DRAGGING;滑动(手指在屏幕上)SCROLL_STATE_SETTLING;滑动(手指移开屏幕)*/LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();// 当不滑动时if (newState == RecyclerView.SCROLL_STATE_IDLE) {//返回最后一个完成可见视图位置int lastItemPosition = manager.findLastCompletelyVisibleItemPosition();int itemCount = manager.getItemCount();// 判断是否滑动到了最后一个item,并且是向上滑动if (lastItemPosition == (itemCount - 1) && isScrollUp) {// 加载更多myLoad();}}}@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);/*这个方法实时监测页面(不是手指)滑动距离dx表示横向滑动距离dy表示纵向大于0向上,小于0向下,等于0不滑动*/isScrollUp= dy>=0;}//这里可以用接口回调,然后就不用将此类设置成抽象类,//设置一个回调,public abstract void myLoad();
}

最后主活动类
public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private SwipeRefreshLayout refreshLayout;private MyAdapter myAdapter;private ArrayList<String> list=new ArrayList<String>();private static boolean isloading=false;//判断是否在加载private Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {if(msg.what==1){refreshLayout.setEnabled(true);if (refreshLayout != null && refreshLayout.isRefreshing()) {refreshLayout.setRefreshing(false);}myAdapter.setLoadstate(myAdapter.FINISH);isloading=false;smooth();}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initvew();somelisten();}public void initvew(){refreshLayout= (SwipeRefreshLayout) findViewById(R.id.refresh);//关于SwipeRefreshLayout的其他属性和方法,自行查阅文档recyclerView= (RecyclerView) findViewById(R.id.recycle);for(int i=0;i<25;i++) list.add("item");myAdapter=new MyAdapter(list);recyclerView.setLayoutManager(new LinearLayoutManager(this));//recyclerView.setLayoutManager(new GridLayoutManager(this,3));recyclerView.setAdapter(myAdapter);}public void somelisten(){refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {//避免下拉刷新与上拉刷新冲突(虽然可能性很小),进行屏蔽,保证只有一个刷新if(!isloading){isloading=true;list.add(0,"newitem");httppost();}}});recyclerView.addOnScrollListener(new FootScrollListener() {@Overridepublic void myLoad() {/*SwipeRefreshLayout刷新加载的时候屏蔽了下拉刷新事件,避免同时刷新多次但是我们自定义的上拉刷新不能自己屏蔽,我们这里用静态变量来实现屏蔽功能*/if(!isloading){Log.e("刷新","进入");myAdapter.setLoadstate(myAdapter.LOADING);isloading=true;refreshLayout.setEnabled(false);//上拉刷新的时候屏蔽掉下拉刷新if (list.size() < 28) {//网络请求//list.add("lastitem");httppost();} else {// 显示加载到底的提示myAdapter.setLoadstate(myAdapter.END);}}}});}//recyclerview滑动到适当位置public void smooth(){/*getChildAt返回组中指定位置的视图,组是指屏幕显示的item组*getTop返回此视图相对于其父项顶部的位置*smoothScrollBy沿任意轴给定的像素滑动*关于recyclerview滑动最常用的是smoothScrollToPosition,不做讲解* */int top=recyclerView.getChildAt(0).getTop();Log.e("top", String.valueOf(top));recyclerView.smoothScrollBy(0,top);Log.e("count", String.valueOf(recyclerView.getChildCount()));}public void httppost(){final OkHttpClient client=new OkHttpClient();RequestBody formBody = new FormEncodingBuilder().add("passwd","123").add("number","123").build();final Request request=new Request.Builder().url("http://10.126.149.157:8080/Test/HelloServlet").post(formBody).build();new Thread(){@Overridepublic void run() {Response response = null;try {response = client.newCall(request).execute();if (response.isSuccessful()) {Log.e("结果", response.body().string());handler.sendEmptyMessage(1);}else {Log.e("结果", "请求出错");handler.sendEmptyMessage(1);}} catch (Exception e) {e.printStackTrace();Log.e("结果", "抛出异常");handler.sendEmptyMessageDelayed(1,500);}}}.start();}
}

我这里是直接拿了以前的OKhttp的一个代码段,当然服务器没开,这里就有一点需要注意的了,有时候网络请求需要很长时间才结束,在实际开发中肯定是不行,然后你可以再加一个计时器在里面,当请求时间过长时,直接停止刷新提示网络超时。


还有一个大问题,那就是当recyclerview是表格布局的时候,加的那个footer也是表格的一格,这样显得非常难看。所以要重写Adapter里这个函数onAttachedToRecyclerView 

根据文档解释,在recyclerview observe这个适配器的时候调用这个方法。通过这个方法判断网格布局的格数然后给footer设置占几个item。但是要注意,在你的主活动中必须将setadapter放在setlayout后面,因为这个方法里面做了网格布局的判断,设置了网格布局才有效。代码如下

 //setadapter必须放在setlayout的后面,不然不会调用到这个方法@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();if (manager instanceof GridLayoutManager) {final GridLayoutManager gridManager = ((GridLayoutManager) manager);gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {// 如果当前是footer的位置,那么该item占据2个单元格,正常情况下占据1个单元格return getItemViewType(position) == FOOT ? gridManager.getSpanCount() : 1;}});}}

最后说几点应当注意的地方。上拉或者下拉正在刷新的时候应该不然它触发新的刷新,虽然这种情况很少,但是也要避免。网络请求的时候,时间是不可控的,有时候时间过长影响体验,所以应该在设一个计时器,刷新达到一定时间据强制关闭刷新并提醒(我的代码中没写这一段的代码)。当上拉的时候底部的footer应该要有不让它显示出来,这样有拖动效果,而这一部分区域正好用来被上拉刷新替换。然后刷新完后,footer还在,所以要上滑一段距离。最后再给一张改进过的效果图


代码已上传:http://download.csdn.net/download/lhp15575865420/10112127


http://chatgpt.dhexx.cn/article/B67RQLEs.shtml

相关文章

Flutter 实现下拉刷新和上拉加载

参考 Flutter下拉刷新和上拉加载更多 下拉刷新 上拉加载更多 下拉刷新直接用flutter自带的控件RefreshIndicator组件即可&#xff0c;上拉加载可以通过ListView 中的ScrollController 属性&#xff0c;根据 ListView 的位置来判断是否滑动到了底部来做加载更多的处理 下面用们用…

iOS 下拉刷新

移动应用开发中有这么一种场景&#xff0c;就是在列表中显示的数据刷新&#xff0c;有点击刷新按钮刷新的&#xff0c;也有现在最流行的由Twitter首先推出的下拉刷新功能&#xff0c;在IOS中&#xff0c;使用下拉刷新更新UITableView中的数据也用的非常多&#xff0c;最典型的就…

uniapp几种实现下拉刷新的方式

一.自带刷新 1.在pages.json 上进行定义 2.在页面上监听下拉动作进行需要的操作 ps&#xff1a;一定要手动停止刷新&#xff0c;否则会一直刷新 自带刷新的优点&#xff1a;相对稳定&#xff0c;写法相对简单 自带刷新的缺点&#xff1a;样式上固定的 所以不能满足全部人的需…

小程序下拉刷新的实现

小程序下拉刷新 1.使用onPullDownRefresh()这个方法来实现下拉刷新 例子如下&#xff1a; // 下拉刷新onPullDownRefresh: function () {wx.showNavigationBarLoading() //在标题栏中显示加载图标setTimeout(() > {wx.hideNavigationBarLoading(); //完成停止加载wx.stopP…

Android 下拉刷新实践

1. 手动实现一个下拉刷新功能。 2. 效果图&#xff1a; 3. view结构 4.实现思路 <com.luocc.tim.recycler.RefreshLayoutandroid:layout_width"match_parent"android:layout_height"wrap_content"android:orientation"vertical"><Tex…

【uniapp】页面下拉刷新

目录 一、全局 二、局部 1、一个页面一个下拉刷新 2、一个页面多个下拉刷新&#xff08;切换时滚动条回到顶部&#xff09; 3、一个页面多个下拉刷新&#xff08;切换时恢复滚动条位置&#xff09; 一、全局 修改pages.json的"enablePullDownRefresh": true, …

uniapp 下拉刷新

uniapp 下拉刷新&#xff08;全局&单页面&#xff09; 全局设置 在pages.json文件的globalStyle对象中开启enablePullDownRefresh属性 单页面 在pages.json文件中的pages数组中找到对应的页面&#xff0c;在对应页面的style属性中开启enablePullDownRefresh属性 下拉刷…

Android 下拉刷新框架实现

前段时间项目中用到了下拉刷新功能&#xff0c;之前在网上也找到过类似的demo&#xff0c;但这些demo的质量参差不齐&#xff0c;用户体验也不好&#xff0c;接口设计也不行。最张没办法&#xff0c;终于忍不了了&#xff0c;自己就写了一个下拉刷新的框架&#xff0c;这个框架…

Android中实现下拉刷新

需求&#xff1a;项目中的消息列表界面要求实现类似sina微博的下拉刷新&#xff1b; 思路&#xff1a;一般的消息列表为ListView类型&#xff0c;将list加载到adapter中&#xff0c;再将adapter加载到ListView中&#xff0c;从而实现消息列表的展示。而下拉刷新要求给消息列表…

微信小程序下拉刷新

一、如何设置微信小程序所有页面都可以下拉刷新呢&#xff1f; 1、在app.json的"window"中进行配置 &#xff08;1&#xff09;把"backgroundTextStyle":“light"改为"backgroundTextStyle”:“dark” &#xff08;2&#xff09;添加"enab…

下拉刷新上拉加载

目录 原理实现效果 原理 想必使用过微信开发工具的应该都接触过上拉加载下拉刷新配置。 原理呢就是通过根据当前刚开始触碰的屏幕垂直y轴距离和滑动时所触碰垂直y轴距离&#xff0c;从而来判断是上拉&#xff0c;下拉。 实现 使用的vue2 封装的组件&#xff0c;js大致思路是…

Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能

转载请注明出处&#xff1a;http://blog.csdn.net/guolin_blog/article/details/9255575 最近项目中需要用到ListView下拉刷新的功能&#xff0c;一开始想图省事&#xff0c;在网上直接找一个现成的&#xff0c;可是尝试了网上多个版本的下拉刷新之后发现效果都不怎么理想。有些…

【Demo】教你实现下拉刷新

前言 第三方库很常见&#xff0c;我们开发需求的时候经常会用到下拉刷新组件&#xff0c;如果要我们自己实现下拉刷新该如何实现尼&#xff1f; 效果 实现原理 1、监听 touchstart事件记录初始startY 2、监听 touchmove事件 e.touches[0].pageY - startY得到 deltaY&#xf…

如何实现上拉加载,下拉刷新

答&#xff1a;下拉刷新和上拉加载这两种交互⽅式通常出现在移动端中 本质上等同于PC⽹⻚中的分⻚&#xff0c;只是交互形式不同 开源社区也有很多优秀的解决⽅案&#xff0c;如 iscroll 、 better-scroll 、 pulltorefresh.js 库等等 这些第三⽅库使⽤起来⾮常便捷 我们通…

jira使用教程管理项目

添加工作流 1.点击项目设置 2.点击工作流&#xff0c;然后点击切换方案 3.进入切换方案界面之后&#xff0c;点击工作流&#xff0c;然后点击添加工作流 4.输入工作流名称&#xff0c;点击添加 5.编辑工作流 可以导出工作流供别人使用 编辑之前添加的工作流 提交bug

今日记录:JIRA使用指南

JIRA流程与使用指南 学习总结&#xff1a; 什么是JIRA&#xff1f;为什么要用任务管理工具&#xff1f;JIRA基础流程 ① 什么是JIRA&#xff1f; JIRA是一个项目与事务管理工具&#xff0c;被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪和敏捷管理等工作领…

JIRA-使用教程_概念

博客概要 JIRA是一个非常强大的项目与事务跟踪工具&#xff0c;博主在具体工作使用中对它爱不释手 &#xff0c;发现它功能全面、配置灵活、扩展丰富…反正优点一大堆&#xff01;好东西嘛就要拿出来&#xff0c;大家一起分享~本博文先简单介绍JIRA相关的基本信息。 文章目录 博…

Confluence+Jira使用

Jira过滤器的使用方式&#xff1a; project MCU AND issuetype 测试用例 AND component GPIO ORDER BY summary ASC实例&#xff1a;

jira使用教程 一(从官方文档理解)

JIRA官方说明 JIRA使用教程 blog QA: jira 如何关联到Gerrit Reviews JIRA Concepts - Issues Aim JIRA tracks issues, which can be bugs, feature requests, or any other tasks you want to track. JIRA可以跟踪问题&#xff0c;可以是bug、特性请求或任何其他你想跟踪…

JIRA-使用教程_问题单-新建

博客概要 简单分享新增并查看一个问题单的步骤~ 文章目录 博客概要《JIRA-使用教程》_总目录问题单-新建1.进入项目2.新建唤起3.填写新建弹窗4.查看问题 总结 《JIRA-使用教程》_总目录 文章超链接&#xff1a;https://blog.csdn.net/qq_41386332/article/details/108865809 …