Android下拉刷新和上拉加载更多


下拉刷新

通过android系统提供的组件:SwipeRefreshLayout

一、基本使用
1 xml中 添加 SwipeRefreshLayout 组件
该组件包含着要操作下拉刷新的控件 如ListView RecyclerView 等
注意这里的SwipeRefreshLayout组件的子布局只能有一个

.support.v4.widget.SwipeRefreshLayout        android:id="@+id/swipe_refresh_layout"        android:layout_below="@+id/dividerimage0"        android:layout_width="match_parent"        android:layout_height="match_parent"        >        .support.v7.widget.RecyclerView            android:id="@+id/recyclerView"            android:layout_width="match_parent"            android:layout_height="match_parent"            >        .support.v7.widget.RecyclerView>    .support.v4.widget.SwipeRefreshLayout>

2 java代码中初始化

 private SwipeRefreshLayout swipeRefreshLayout;swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);

3 设置刷新时的颜色变化

  swipeRefreshLayout.setColorSchemeResources(                R.color.colorPrimary,                R.color.green,                R.color.red        );

4 所在Activity类也要implements SwipeRefreshLayout.OnRefreshListener


5 重写下拉刷新方法

@Override    public void onRefresh() {          // 网络请求        okHttp.getHandler(handlerForGenJin);        // 这里用sortWay变量 这样即使下拉刷新也能保持用户希望的排序方式        askForOkHttp(sortWay);    }

6 当网络请求完 获取并解析了数据,通知结束下拉刷新

  // 通知结束下拉刷新  handlerForRefresh.sendEmptyMessage(0x93);

7

Handler handlerForRefresh = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case 0x93: {                    swipeRefreshLayout.setRefreshing(false);                }            }        }    };

8 开启监听
onCreate()中

swipeRefreshLayout.setOnRefreshListener(this);

问题:当下拉刷新后,会发现Item之间的间距增大,刷新一次增大一次
分析:因为你每次调用initView ,这样每次都会执行

  mRecyclerView.addItemDecoration(new MyDividerItemDecoration(                    this, DividerItemDecoration.VERTICAL));

也就是每次都会加一次分隔线,因此要设置一个boolean变量的值,判断是否是第一次加载界面,是的话就加分隔线,否则就不加分隔线了

 if (IsFirstOnCreate) {            mRecyclerView.addItemDecoration(new MyDividerItemDecoration(                    this, DividerItemDecoration.VERTICAL));            IsFirstOnCreate = false;        }

从别的界面回传通知本界面执行下拉刷新
通过 intent 的 startActivityForResult方式去跳转 设置请求码回传码
在onActivityResult中:

    @Override    public void onActivityResult(int requestCode,int resultCode,Intent data){        super.onActivityResult(requestCode,resultCode,data);        if(requestCode==0x05){            if(resultCode==0x05){                swipeRefreshLayout.setOnRefreshListener(this);                swipeRefreshLayout.post(new Runnable() {                    @Override                    public void run() {                        swipeRefreshLayout.setRefreshing(true);                    }                });                this.onRefresh();            }        }    }

上拉加载更多

主要是利用RecyclerView自带的ScrollListener去监听是否滑动到了底部

设置底部的Item样式

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical">    <TextView        android:id="@+id/foot_tips"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center"        android:textSize="15sp"        android:padding="10dp"        android:layout_marginBottom="1dp"/>LinearLayout>

Activity中

    private LinearLayoutManager mLayoutManager;                   private static boolean hasMore = false; // 是否有下一页    private static int currentPage ;    // 若是上拉加载更多的网络请求 则不需要删除数据    private boolean isLoadingMore = false;    // 最后一个条目位置    private static int lastVisibleItem = 0;

oncreate中

loadingMore();// 初始currentPage为1currentPage = 1;// 网络请求askForOKHttp(sortWay);

loadingMore()监听方法:

private void loadingMore(){// 实现上拉加载重要步骤,设置滑动监听器,RecyclerView自带的ScrollListenermRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {   @Override   public void onScrollStateChanged(RecyclerView recyclerView, int newState) {       super.onScrollStateChanged(recyclerView, newState);       if(!isLoadingMore){        // 若不是加载更多 才 加载       // 在newState为滑到底部时       if (newState == RecyclerView.SCROLL_STATE_IDLE) {           // 如果没有隐藏footView,那么最后一个条目的位置(带数据)就比我们的getItemCount少1           if (!mAdapter.isFadeTips() && lastVisibleItem + 1 == mAdapter.getItemCount()) {               // 然后调用updateRecyclerview方法更新RecyclerView               updateRecyclerView();           }           // 如果隐藏了提示条,我们又上拉加载时,那么最后一个条目(带数据)就要比getItemCount要少2           if (mAdapter.isFadeTips() && lastVisibleItem + 2 == mAdapter.getItemCount()) {               // 然后调用updateRecyclerview方法更新RecyclerView               updateRecyclerView();    // 要调           }       }     }     }   //滚动监听 @Override   public void onScrolled(RecyclerView recyclerView, int dx, int dy) {       super.onScrolled(recyclerView, dx, dy);       // 在滑动完成后,拿到最后一个可见的item的位置       lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();   }});

mLayoutManager要为 LinearLayoutManager 类型的

  // 上拉加载时调用的更新RecyclerView的方法    private void updateRecyclerView() {      if(hasMore){          // 还有下一页 网络请求 第二页 第三页          currentPage++;    // 加1           isLoadingMore = true;          askForOKHttp(sortWay);     }

Adapter中:
声明:

    private int normalType = 0;     // 第一种ViewType,正常的item    private int footType = 1;       // 第二种ViewType,底部的提示View    private static boolean hasMore = true;   // 变量,是否有更多数据    private boolean fadeTips = false; // 变量,是否隐藏了底部的提示

构造方法的形参 除了传入数据,增加一个hasMore变量 用于判断是否有更多

更新数据也是

    /**     *  更新数据      */    public void updateData(ArrayList array0,                            ArrayList array1,ArrayList array2,                            ArrayList array3,boolean mHasMore) {        this.arrayList0 = array0;          this.arrayList5 = array1;           this.arrayList2 = array2;           this.arrayList3 = array3;           hasMore = mHasMore;        notifyDataSetChanged();    }

onCreateViewHolder 中: 设置不同的viewHolder (分数据item和底部foot item)

@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {   if (viewType == normalType) {       ViewHolder viewHolder = null;          // 实例化展示的view         View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_choose_customer, parent, false);         // 实例化viewholder          viewHolder = new ViewHolder(v, mItemClickListener);       return viewHolder;   }else {       View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_foot_layout, parent, false);       FootHolder footHolder = new FootHolder(v);       return footHolder;   }}

onBindViewHolder中:

@Override    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {        // 如果是正常的imte,直接设置TextView的值        if (holder instanceof ViewHolder) {           ((ViewHolder) holder).customerName.setText(arrayList0.get(position));          ((ViewHolder) holder).qiangduo.setOnClickListener(new View.OnClickListener() {                        @Override                        public void onClick(View v) {                            mItemInnerDeleteListener.onItemInnerDeleteClick(position);                        }                    });    }else {            if (hasMore) {                // 不隐藏footView提示                fadeTips = false;                if (arrayList0.size() > 0) {                    // 如果查询数据发现增加之后,就显示正在加载更多                    ((FootHolder) holder).tips.setVisibility(View.VISIBLE);                    ((FootHolder) holder).tips.setText("正在加载更多...");                }            } else {                if (arrayList0.size() > 0) {                    // 如果查询数据发现并没有增加时,就显示没有更多数据了                    ((FootHolder) holder).tips.setText("暂无更多数据");                    // 然后通过主线程延时让这个提示消失,在1000ms后执行                    mHandler.postDelayed(new Runnable() {                        @Override                        public void run() {                            // 隐藏提示条                            ((FootHolder) holder).tips.setVisibility(View.GONE);                            // 将fadeTips设置true                            fadeTips = true;                            // hasMore设为true是为了让再次拉到底时,会先显示正在加载更多                            hasMore = true;                        }                    }, 1000);                }            }        }    }            
 @Override    public int getItemCount() {        // 获取item的数量   计上footView        return arrayList0 == null ? 0 : arrayList0.size()+1;    }    // 自定义方法,获取数据的最后一个位置,不计上footView    public int getRealLastPosition() {        return arrayList0.size();    }
// 根据条目位置返回ViewType,以供onCreateViewHolder方法内获取不同的Holder    @Override    public int getItemViewType(int position) {        if (position == getItemCount() - 1) {            return footType;        } else {            return normalType;        }    }
 // 暴露接口,改变fadeTips的方法    public boolean isFadeTips() {        return fadeTips;    }
   // 正常item的ViewHolder,用以缓存findView操作     class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{      TextView XXX XXX XXX ;        private MyItemClickListener mListener;        ...        ...        }
   // 底部footView的ViewHolder,用以缓存findView操作    class FootHolder extends RecyclerView.ViewHolder {        private TextView tips;        FootHolder(View itemView) {            super(itemView);            tips = itemView.findViewById(R.id.foot_tips);        }    }

也可以使用第三方库实现上拉加载 下拉刷新

参考:https://github.com/scwang90/SmartRefreshLayout

上部和下部的会隐藏 然后下拉或者上拉 都会显示 然后过一定时间又会收回

和RecyclerView结合,则会有默认的一个 刷新样式

包括RecyclerView和其他组件,recyclerView控件上方/下方的组件 会作为 刷新的控件,设置控件的动画样式即为刷新或者加载的动画样式

只能设置3个子View 否则报错
Caused by: java.lang.RuntimeException: 最多只支持3个子View,Most only support three sub view
如:

<com.scwang.smartrefresh.layout.SmartRefreshLayout        android:id="@+id/smartRefresh"        android:layout_width="match_parent"        android:layout_height="match_parent"        >        "@+id/imageView0"            android:layout_width="match_parent"            android:layout_height="50dp"            />        .support.v7.widget.RecyclerView            android:layout_width="match_parent"            android:layout_height="match_parent">        .support.v7.widget.RecyclerView>        <com.scwang.smartrefresh.layout.footer.BallPulseFooter            android:layout_width="match_parent"            android:layout_height="50dp"/>    com.scwang.smartrefresh.layout.SmartRefreshLayout>

待处理:限制下拉和上拉加载的高度限制


有三种添加的方式:

1 在 App extends Application的类中
static静态代码块中
优先级最低
2 在XML中

<com.scwang.smartrefresh.layout.SmartRefreshLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        >

使用 提供的 一些 好看的效果
如上方的

<com.scwang.smartrefresh.layout.footer.BallPulseFooter

也可以自己设置为自定义的 组件
如上方的

 

java中开启帧动画

 ImageView imageView = findViewById(R.id.imageView0);        imageView.setImageResource(R.drawable.run_animation_list);        AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();        animationDrawable.start();

3 java代码设置

final RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.refreshLayout);//设置 Header 为 贝塞尔雷达 样式refreshLayout.setRefreshHeader(new BezierRadarHeader(this).setEnableHorizontalDrag(true));//设置 Footer 为 球脉冲 样式refreshLayout.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));

更多相关文章

  1. android存取数据方式:文件、SharedPreferences
  2. android5中数据存储方式详解
  3. 实现Android ListView 自动加载更多内容
  4. Android 系统数据库编程学习日志
  5. 学习笔记(六) 网络编程与数据处理
  6. Android中数据存储的5中方法
  7. Android 5.1 close data flow 数据关闭流程

随机推荐

  1. Android BaseAdapter如何获得每一项并添
  2. Android Kotlin继承
  3. 在android studio的虚拟机的sd卡上创建文
  4. android图片裁剪
  5. Android弹出对话框简单代码
  6. 使用universal-image-loader中出现的EOFE
  7. android编译系统之后刷img
  8. Android 开发架构学习篇
  9. Android(安卓)7.0新特性概览
  10. The specified Android SDK Build Tools