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(安卓)ListView 自动加载更多内容
  2. Android四种Activity的加载模式
  3. Android开发实践 带你理解使用WebView
  4. Android高效加载大图、多图解决方案,有效避免程序OOM
  5. android 自定义Dialog(背景图等)
  6. michael / afinal
  7. Android实现系统下拉栏的消息提示——Notification
  8. Android(安卓)studio 下拉刷新,加载更多使用LoadingViewFinal
  9. Android(安卓)关于WebView加载完成的多种监听方式

随机推荐

  1. 对于PHP中enum的好奇
  2. redis界面管理工具phpRedisAdmin 安装
  3. 分支复位组的反向引用
  4. php不重新编译添加模块 php不重新编译添
  5. PHP万能密码登陆
  6. php 7-177之间能被7整除的总和的平均数
  7. php如何跨站抓取别的站点的页面的补充
  8. 如何让Netbeans调试器暂停每个新的php文
  9. 执行以下查询时出错
  10. wordpress永久链接重新加载页面,而不是重