PullToRefresh和SwipeRefreshLayout的使用

news/2024/7/4 12:27:39

 

PullToRefresh是一套实现非常好的下拉刷新库(下载地址:https://github.com/chrisbanes/Android-PullToRefresh),它支持:

1.ListView

2.ExpandableListView

3.GridView

4.WebView

5.ScrollView

6.Horizontal ScrollView

7.ViewPager

等多种常用的需要刷新的View类型,而且使用起来也十分方便。下载下来解压里面有extras,library,sample这三个文件夹。sample是demo,libarary是类库,我们主要用到的是library这个文件夹。下面就用官网给的demo来具体说明如何使用吧,下面介绍下ListView的使用

使用时直接在布局中引用即可

<com.handmark.pulltorefresh.library.PullToRefreshListView
    android:id="@+id/pull_refresh_list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:cacheColorHint="#00000000"
    android:divider="#19000000"
    android:dividerHeight="4dp"
    android:fadingEdge="none"
    android:fastScrollEnabled="false"
    android:footerDividersEnabled="false"
    android:headerDividersEnabled="false"
    android:smoothScrollbar="true" />

在其他布局文件中,我们也许会看到xmlns:ptr="http://schemas.android.com/apk/res-auto"这个自定义的命名空间,看一下这个控件里面的一些基本属性:

          1.ptr:ptrDrawable="";//这里可以设置自己的上拉下拉图标。

          2.ptr:ptrHeaderBackground="";//上拉时底部的背景色,下拉时头部的背景色

          3.ptr:ptrHeaderTextColor="";//上拉,下拉时Header,Footer显示的字体颜色

          4.ptr:ptrHeaderSubTextColor="";//上拉,下拉Header,Footer中上次刷新时间的颜色

          5.ptr:ptrShowIndicator="";//true时会在控件的右上角和右下角出现设置的icon

          6.ptr:ptrAnimationStyle="";//显示时候图标的取值 ;flip:翻转;rotate:旋转

          7.ptr:ptrRotateDrawableWhilePulling="";//当动画为rotate时,下拉是否旋转

          8.ptr:ptrRefreshableViewBackground="";//设置整个控件布局的背景颜色

          9.ptr:ptrScrollingWhileRefreshingEnabled="";//刷新的时候是否允许ListView或者GridView滚动。推荐使用true

          10.ptr:prtListViewExtrasEnabled="";//决定Header,Footer以何种方式加入PullToRefreshListView.其中为true时,就是以Header的方式加入,在滚动刷新时头部会跟着一起滚动;为false时,就是以Footer的方式加入,在滚动的时候底部会跟着一起滚动。

          11.ptr:ptrMode="";//设置是上拉,下拉还是两者都支持。both:两者都支持;disabled:禁用下拉刷新;pullFromStart:仅支持下拉刷新;pullUpFromBottom:仅支持上拉加载;manualOnly:只允许手动触发。(注意:如果不在代码设置它默认的就只有下拉刷新)

以上只是一些基本属性:一般你用的什么控件它都包含原有控件的所有属性,如你使用的是PullToRefreshListView那么它里面同样包含ListView的一些属性。同样上面的属性你都可以在代码中去set***使用。

Activity代码:

public final class PullToRefreshListActivity extends ListActivity {

    static final int MENU_MANUAL_REFRESH = 0;
    static final int MENU_DISABLE_SCROLL = 1;
    static final int MENU_SET_MODE = 2;
    static final int MENU_DEMO = 3;

    private LinkedList<String> mListItems;
    private PullToRefreshListView mPullRefreshListView;
    private ArrayAdapter<String> mAdapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ptr_list);

        mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);
//    mPullRefreshListView.setMode(Mode.BOTH);
        // Set a listener to be invoked when the list should be refreshed.
        mPullRefreshListView
                .setOnRefreshListener(
                        //双向滑动
//                new OnRefreshListener2<ListView>() {
//
//             @Override
//             public void onPullDownToRefresh(
//                   PullToRefreshBase<ListView> refreshView) {
//                // TODO Auto-generated method stub
//                new GetDataTask().execute();
//             }
//
//             @Override
//             public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
//                // TODO Auto-generated method stub
//                new GetDataTask().execute();
//             }
//             
//          }
//       );
                        //单方向滑动
                        new OnRefreshListener<ListView>() {
                            @Override
                            public void onRefresh(
                                    PullToRefreshBase<ListView> refreshView) {
                                String label = DateUtils.formatDateTime(
                                        getApplicationContext(),
                                        System.currentTimeMillis(),
                                        DateUtils.FORMAT_SHOW_TIME
                                                | DateUtils.FORMAT_SHOW_DATE
                                                | DateUtils.FORMAT_ABBREV_ALL);

                                // Update the LastUpdatedLabel
                                refreshView.getLoadingLayoutProxy()
                                        .setLastUpdatedLabel(label);

                                // Do work to refresh the list here.
                                new GetDataTask().execute();
                            }
                        });

        // Add an end-of-list listener
        mPullRefreshListView
                .setOnLastItemVisibleListener(new OnLastItemVisibleListener() {

                    @Override
                    public void onLastItemVisible() {
                        Toast.makeText(PullToRefreshListActivity.this,
                                "End of List!", Toast.LENGTH_SHORT).show();
                    }
                });

        ListView actualListView = mPullRefreshListView.getRefreshableView();

        // Need to use the Actual ListView when registering for Context Menu
        registerForContextMenu(actualListView);

        mListItems = new LinkedList<String>();
        mListItems.addAll(Arrays.asList(mStrings));

        mAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, mListItems);

        /**
         * Add Sound Event Listener
         */
        SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(
                this);
        soundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event);
        soundListener.addSoundEvent(State.RESET, R.raw.reset_sound);
        soundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound);
        mPullRefreshListView.setOnPullEventListener(soundListener);

        // You can also just use setListAdapter(mAdapter) or
        // mPullRefreshListView.setAdapter(mAdapter)
        actualListView.setAdapter(mAdapter);
    }

    private class GetDataTask extends AsyncTask<Void, Void, String[]> {

        @Override
        protected String[] doInBackground(Void... params) {
            // Simulates a background job.
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
            }
            return mStrings;
        }

        @Override
        protected void onPostExecute(String[] result) {
            mListItems.addFirst("Added after refresh...");
            mAdapter.notifyDataSetChanged();

            // Call onRefreshComplete when the list has been refreshed.
            mPullRefreshListView.onRefreshComplete();

            super.onPostExecute(result);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, MENU_MANUAL_REFRESH, 0, "Manual Refresh");
        menu.add(
                0,
                MENU_DISABLE_SCROLL,
                1,
                mPullRefreshListView.isScrollingWhileRefreshingEnabled() ? "Disable Scrolling while Refreshing"
                        : "Enable Scrolling while Refreshing");
        menu.add(
                0,
                MENU_SET_MODE,
                0,
                mPullRefreshListView.getMode() == Mode.BOTH ? "Change to MODE_PULL_DOWN"
                        : "Change to MODE_PULL_BOTH");
        menu.add(0, MENU_DEMO, 0, "Demo");
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
                                    ContextMenuInfo menuInfo) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;

        menu.setHeaderTitle("Item: "
                + getListView().getItemAtPosition(info.position));
        menu.add("Item 1");
        menu.add("Item 2");
        menu.add("Item 3");
        menu.add("Item 4");

        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem disableItem = menu.findItem(MENU_DISABLE_SCROLL);
        disableItem
                .setTitle(mPullRefreshListView
                        .isScrollingWhileRefreshingEnabled() ? "Disable Scrolling while Refreshing"
                        : "Enable Scrolling while Refreshing");

        MenuItem setModeItem = menu.findItem(MENU_SET_MODE);
        setModeItem
                .setTitle(mPullRefreshListView.getMode() == Mode.BOTH ? "Change to MODE_FROM_START"
                        : "Change to MODE_PULL_BOTH");

        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case MENU_MANUAL_REFRESH:
                new GetDataTask().execute();
                mPullRefreshListView.setRefreshing(false);
                break;
            case MENU_DISABLE_SCROLL:
                mPullRefreshListView
                        .setScrollingWhileRefreshingEnabled(!mPullRefreshListView
                                .isScrollingWhileRefreshingEnabled());
                break;
            case MENU_SET_MODE:
                mPullRefreshListView
                        .setMode(mPullRefreshListView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START
                                : Mode.BOTH);
                break;
            case MENU_DEMO:
                mPullRefreshListView.demo();
                break;
        }

        return super.onOptionsItemSelected(item);
    }

       
    private String[] mStrings = {"Abbaye de Belloc",
            "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu",
            "Airag", "Airedale", "Aisy Cendre", "Allgauer Emmentaler",
            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
            "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
            "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
            "Allgauer Emmentaler"
    };
}

具体说下代码,初始化PullToRefreshListView,刷新模式可以在xml文件中进行设置,也可以在java代码中通过setMode()设置,然后设置监听器OnRefreshListener,但这个监听器只能监听一个方向的,如果要实现两个方向那么就使用OnRefreshListener2监听器,同时别忘了了设置模式为Mode.BOTH。

 

但是PullToRefresh作者已经好久不更新了,现在很多人也在此基础上做了很多的扩展,大家可以上网自己搜下。google官方在最新的android.support.v4包中增加了一个新类SwipeRefreshLayout,这个类的作用就是提供官方的下拉刷新,并且效果相当不错,而上拉加载更多则用我们自定义的listview,也是相当简单,我们在下面的例子就用一个最简单的例子去实现一个我们的上拉加载、下拉刷新的功能。它是一个viewgroup,但是它只允许有一个子控件,子控件能是任何view,使用的时候,所在类实现OnRefreshListener接口,在onRefresh()方法中实现所要完成的任务。好了,现在思路明确了,SwipeRefreshLayout已经实现了下拉刷新的功能,我们要做的就是实现一个能够上拉加载的组件,然后放到SwipeRefreshLayout中即可,好,上代码:

自定义一个ListView:

public class LoadMoreListView extends ListView implements OnScrollListener {
   /**
    * 滑动到最下面时的上拉操作
    */
   private int mTouchSlop;
   /**
    * ListView的加载中footer
    */
   private View mListViewFooter;
   /**
    * 上拉监听器, 到了最底部的上拉加载操作
    */
   private OnLoadMoreListener mOnLoadMoreListener;
   /**
    * 按下时的y坐标
    */
   private int mYDown;
   /**
    * 抬起时的y坐标, 与mYDown一起用于滑动到底部时判断是上拉还是下拉
    */
   private int mLastY;
   /**
    * 是否在加载中 ( 上拉加载更多 )
    */
   private boolean isLoading = false;

   /**
    * 加载更多的监听器
    */
   public static interface OnLoadMoreListener {
      public void onLoad();
   }

   public LoadMoreListView(Context context, AttributeSet attrs) {
      super(context, attrs);
      mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
      mListViewFooter = LayoutInflater.from(context).inflate(
            R.layout.listview_footer, null, false);
      this.addFooterView(mListViewFooter);
      mListViewFooter.setVisibility(View.GONE);
      this.setOnScrollListener(this);
   }

   public LoadMoreListView(Context context) {
      super(context);
      // TODO Auto-generated constructor stub
   }

   /**
    * @param loadMoreListener
    */
   public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
      mOnLoadMoreListener = loadMoreListener;
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent event) {
      final int action = event.getAction();

      switch (action) {
      case MotionEvent.ACTION_DOWN:
         // 按下
         mYDown = (int) event.getRawY();
         break;

      case MotionEvent.ACTION_MOVE:
         // 移动
         mLastY = (int) event.getRawY();
         break;

      case MotionEvent.ACTION_UP:
         // 抬起
         if (canLoad()) {
            loadData();
         }
         break;
      default:
         break;
      }

      return super.dispatchTouchEvent(event);
   }

   /**
    * @param loading
    */
   public void setLoading(boolean loading) {
      isLoading = loading;
      if (isLoading) {
         mListViewFooter.setVisibility(View.VISIBLE);
      } else {
         mListViewFooter.setVisibility(View.GONE);
         mYDown = 0;
         mLastY = 0;
      }
   }

   @Override
   public void onScrollStateChanged(AbsListView view, int scrollState) {
      // 滚动时到了最底部也可以加载更多
      if (canLoad()) {
         loadData();
      }
   }

   @Override
   public void onScroll(AbsListView view, int firstVisibleItem,
         int visibleItemCount, int totalItemCount) {

   }

   /**
    * 是否可以加载更多, 条件是:到了最底部, listView不在加载中且为上拉操作.
    * 
    * @return
    */
   private boolean canLoad() {
      return isBottom() && !isLoading && isPullUp();
   }

   /**
    * 如果到了最底部,而且是上拉操作.那么执行onLoad方法
    */
   private void loadData() {
      if (mOnLoadMoreListener != null) {
         // 设置状态
         setLoading(true);
         //
         mOnLoadMoreListener.onLoad();
      }
   }

   /**
    * 判断是否到了最底部
    */
   private boolean isBottom() {

      if (this.getAdapter() != null) {
         return this.getLastVisiblePosition() == (this.getAdapter()
               .getCount() - 1);
      }
      return false;
   }

   /**
    * 是否是上拉操作
    * 
    * @return
    */
   private boolean isPullUp() {
      return (mYDown - mLastY) >= mTouchSlop;
   }

}

我们实现了OnScrollListener监听器,同时写了一个OnLoadMoreListener 监听器接口,然后在OnScrollListener中回调相关定义的方法,而接口的具体操作就需要我们在ListView的实现类中实现了

 

而主布局就相当简单了,直接在SwipeRefreshLayout布局中加入我们的ListView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <com.xmr.swiperefreshlayout.LoadMoreListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
       </com.xmr.swiperefreshlayout.LoadMoreListView>
    </android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>

MainActivity类如下:

public class MainActivity extends Activity implements OnRefreshListener,
      OnLoadMoreListener {
   private SwipeRefreshLayout swipeLayout;
   private LoadMoreListView listView;
   private ArrayAdapter<String> adapter;
   private List<String> list;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      initView();
      setData();
      setListener();
   }

   /**
    * 初始化布局
    */
   private void initView() {
      swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
      swipeLayout.setColorSchemeResources(R.color.color_bule2,
            R.color.color_bule, R.color.color_bule2, R.color.color_bule3);
      listView = (LoadMoreListView) findViewById(R.id.list);
      list = new ArrayList<String>();
      adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, list);
      listView.setAdapter(adapter);
   }

   /**
    * 添加数据
    */
   private void setData() {
      for (int i = 0; i < 10; i++) {
         list.add("itemText" + i);
      }
      adapter.notifyDataSetChanged();
   }

   /**
    * 设置监听
    */
   private void setListener() {
      swipeLayout.setOnRefreshListener(this);
      listView.setLoadMoreListener(this);
   }

   /**
    * 下拉刷新
    */
   @Override
   public void onRefresh() {
      swipeLayout.postDelayed(new Runnable() {

         @Override
         public void run() {
            // 更新数据 更新完后调用该方法结束刷新
            HashMap<String, String> map = new HashMap<String, String>();
            list.add("itemText" + "刷新");

            adapter.notifyDataSetChanged();
            swipeLayout.setRefreshing(false);
         }
      }, 2000);

   }

   /**
    * 加载更多
    */
   @Override
   public void onLoad() {
      swipeLayout.postDelayed(new Runnable() {
         @Override
         public void run() {
            // 更新数据 更新完后调用该方法结束刷新
            listView.setLoading(false);
            HashMap<String, String> map = new HashMap<String, String>();
            list.add("itemText"+ "更多");
            adapter.notifyDataSetChanged();
         }
      }, 2000);
   }

}

最终效果如下:



当然这只是一个最简单的实现,我们完全可以发挥我们的想象力去创造我们想要的效果,我这算是个抛砖引玉的效果吧,技术有限,多有不足之处,请大家多多指教。
参考:

https://github.com/chrisbanes/Android-PullToRefresh

http://blog.csdn.net/ueryueryuery/article/details/17440465/

http://www.itnose.net/detail/6341754.html

http://blog.csdn.net/hhhccckkk/article/details/46971835

http://www.2cto.com/kf/201505/399695.html

http://blog.csdn.net/hongshengpeng/article/details/50187259

http://www.cnblogs.com/JinyaoLi/p/3852424.html

http://blog.csdn.net/zhongkejingwang/article/details/38868463

https://github.com/bingoogolapple/BGARefreshLayout-Android

https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh

 

 

源代码


http://www.niftyadmin.cn/n/3501647.html

相关文章

Linux搭建sendmail服务器

一、安装前准备1.设置静态IP http://love11forever.blog.51cto.com/11313259/18507322.关闭iptableshttp://love11forever.blog.51cto.com/11313259/18469353.关闭selinuxhttp://love11forever.blog.51cto.com/11313259/1846943 二、安装、配置DNS服务1.安装DNS服务yum in…

linux vi查找字符串查找字符串,Linux的vi查找字符串

使用vi编辑器编辑长文件时&#xff0c;常常是头昏眼花&#xff0c;也找不到需要更改的内容。这时&#xff0c;使用查找功能尤为重要。方法如下&#xff1a;1、命令模式下输入“/字符串”&#xff0c;例如“/Section 3”。2、如果查找下一个&#xff0c;按“n”即可。要自当前光…

网页 console的使用

通过按下回车键会触发执行命令&#xff0c;而有时候我们需要执行的逻辑比较复杂&#xff0c;需要多行才可以完成&#xff0c;可以通过点击“shift回车键”来实现换行。在console中&#xff0c;可以实现对按钮的监控。比如此时按钮的文本值为“不可点击”&#xff0c;类名为“bu…

pku 1724 ROADS BFS +优先队列

http://poj.org/problem?id1724 题意&#xff1a; Bob现在有的钱数为k&#xff0c;他想从城市1到城市n&#xff0c;给出m条连接两个城市的有向边&#xff0c;并且给出路的长度w&#xff0c;和经过这条路要交的钱数c。问Bob在花的过路费不超过k的前提下能到达城市n的最短路径为…

5320 软件集合

用户名&#xff1a;fkedwgwy密码:fkedwgwy 《爱她就要学会用她》 目前软件&#xff1a; UC6.0 QQ2008 来电通 天气通 掌上书院 【090609】【5320 软件集合】超强音乐 播放器 MobiFactor PowerMp3 v1.17 完全版 【090609】【5320 软件集合】火烧图文Burn1.2汉化版 【090610】…

centos7 中ifconfig提示-bash

1、检查是否存在ifconfig命令&#xff1a;cat /sbin/ifconfig2、不存在&#xff0c;安装net-toolsyum upgradeyum install net-tools转载于:https://blog.51cto.com/wd0809/1852722

linux重定向文件过大,关于linux:如何将输出重定向到文件和标准输出

在bash中&#xff0c;调用foo将在stdout上显示该命令的任何输出。调用foo > output会将该命令的任何输出重定向到指定的文件(在本例中为"output")。有没有方法将输出重定向到一个文件&#xff0c;并在stdout上显示它&#xff1f;如果有人在这里寻找错误输出到文件…

运维实践

一、批量杀死进程ps -ef |grep mysql | awk {print $2} |head -1|xargs kill -9二、Windows下GBK编码转换UTF8iconv -f GBK -t UTF8 addreezd.csv -o addreezd2.csv三、当Tomcat异常宕机后重启服务#!/bin/bash Tomcatstart"/usr/install/tomcat8/bin/startu…