金田

下拉刷新是一种比较常用的效果,Android 5.0之前官方并未提供类似的控件,App中主要是用的第三方库,例如PullToRefresh,ActionBar-PullToRefresh等。刚好现在项目中需要处理 Android 5.0 材质设计部分的东西,就顺带学习下这部分。

大体介绍一下;

  1. SwipeRefreshLayout是Google在support v4 19.1版本的library更新的一个下拉刷新控件 (android-support-v4.jar)
  2. 目前只支持下拉刷新,不支持上拉加载更多的操作(需要自行进行扩展)
  3. 作为官方自带的控件,相对能能够保证比较好的通用性及风格(这里不包括各种自家定制的系统 L)
  4. SwipeRefreshLayout继承于ViewGroup,ViewGroup中可以包含其他不同控件,so UI定制起来也相对比较容易
  5. 使用起来比较方便,可以很容易的实现Google Now的刷新效果

        SwipeRefreshLayout布局中目前只能包含一个子布局,使用侦听机制来通知刷新事件。例如当用户使用下拉手势时,SwipeRefreshLayout会触发OnRefreshListener,然后刷新事件会在onRefresh()方法中进行处理。当需要结束刷新的时候,可以调用setRefreshing(false)。如果要禁用手势和进度动画,调用setEnabled(false)即可。

 

接下来介绍一下其大体使用方法:

1.布局文件(示例代码)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version= "1.0" encoding= "utf-8" ?> "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:id= "@+id/id_explore_swipe_ly"          android:layout_width= "wrap_content"          android:layout_height= "wrap_content"          android:background= "#ffffff" >                         android:id= "@+id/id_listview"              android:layout_width= "match_parent"              android:layout_height= "match_parent" >                

2.java逻辑代码:

首先需要实现 SwipeRefreshLayout.OnRefreshListener  接口,然后重写方法 onRefresh():

1 2 3 4 5 6 7 8 9 10 11 @Override public void onRefresh() {      new Handler().postDelayed( new Runnable() {            @Override          public void run() {              // 设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。              mSwipeRefreshLayout.setRefreshing( false );          }      }, 3000 ); }

 

现在我们初始化该控件:

1 2 3 4 5 6 7 8 9 10 public void initSwipeRefreshParameters() {      // 设置进度条的颜色变化,最多可以设置4种颜色   mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_green_light,              android.R.color.holo_orange_light, android.R.color.holo_red_light);      // 设置下拉监听,当用户下拉的时候会去执行回调      mSwipeRefreshLayout.setOnRefreshListener( this );      // 调整进度条距离屏幕顶部的距离      mSwipeRefreshLayout.setProgressViewOffset( false , 0 ,              ( int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24 , getResources().getDisplayMetrics())); }

 

以上是基本用法,现在来大体介绍一下定制支持上拉加载的部分,演示图示:

图1 上拉加载效果示意图

 

首先实现SwipeRefreshLayout的重写:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 public class mySwipeRefreshLayout extends SwipeRefreshLayout implements OnScrollListener {        private int mTouchSlop;      private ListView mListView;      private OnLoadListener mOnLoadListener;      private View mListViewFooter;      private int mYDown;      private int mLastY;      private boolean isLoading = false ;        public mySwipeRefreshLayout(Context context) {          this (context, null );      }        public mySwipeRefreshLayout(Context context, AttributeSet attrs) {          super (context, attrs);            mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();            mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer, null , false );      }        @Override      protected void onLayout( boolean changed, int left, int top, int right, int bottom) {          super .onLayout(changed, left, top, right, bottom);            // 初始化ListView对象          if (mListView == null ) {              getListView();          }      }        private void getListView() {          int childs = getChildCount();          if (childs > 0 ) {              View childView = getChildAt( 0 );              if (childView instanceof ListView) {                  mListView = (ListView) childView;                  // 设置滚动监听器给ListView, 使得滚动的情况下也可以自动加载                  mListView.setOnScrollListener( this );              }          }      }        public void setListView(ListView list) {          this .mListView = list;          setLoading( true );          this .mListView.setOnScrollListener( this );      }        @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);      }        /**       * @方法说明:是否可以加载更多, 条件是到了最底部, listview不在加载中, 且为上拉操作.       */      private boolean canLoad() {          return isBottom() && !isLoading && isPullUp();      }        /**       * @方法说明:判断是否到了最底部       */      private boolean isBottom() {          if (mListView != null && mListView.getAdapter() != null ) {              return mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1 );          }          return false ;      }        /**       * @方法说明:是否是上拉操作       */      private boolean isPullUp() {          return (mYDown - mLastY) >= mTouchSlop;      }        /**       * @方法说明: 如果到了最底部,而且是上拉操作.那么执行onLoad方法       */        private void loadData() {          if (mOnLoadListener != null ) {              mOnLoadListener.onLoad();          }          // 设置状态          setLoading( true );      }        /**       * @方法说明:设置刷新       */      public void setLoading( boolean loading) {          isLoading = loading;          if (mListView != null && mListView.getFooterViewsCount() > 0 )              mListView.removeFooterView(mListViewFooter);          if (isLoading) {              if (mListView != null && mListView.getFooterViewsCount() <= 0 )                  mListView.addFooterView(mListViewFooter);          } else {              mYDown = 0 ;              mLastY = 0 ;          }      }        public void setOnLoadListener(OnLoadListener loadListener) {          mOnLoadListener = loadListener;      }        @Override      public void onScrollStateChanged(AbsListView view, int scrollState) {      }        @Override      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {          if (isFastDoubleClick( 100 ))              return ;            // 滚动时到了最底部也可以加载更多          isLoading = false ;          if (canLoad()) {              loadData();          }      }        public View getmListViewFooter() {          return mListViewFooter;      }        /**       * @类描述:加载更多的监听器       */      public static interface OnLoadListener {          public void onLoad();      }        private static long lastClickTime;        public static boolean isFastDoubleClick( long times) {          long time = System.currentTimeMillis();          long timeD = time - lastClickTime;          if ( 0 < timeD && timeD < times) {              return true ;          }          lastClickTime = time;          return false ;      } }

 

MainActivity.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 public class MainActivity extends Activity {      private mydapter adapter;        @Override      protected void onCreate(Bundle savedInstanceState) {          super .onCreate(savedInstanceState);            setContentView(R.layout.main);          adapter = new mydapter();            // 获取RefreshLayout实例          final mySwipeRefreshLayout myRefreshListView = (mySwipeRefreshLayout) findViewById(R.id.swipe_layout);            // 获取listview实例          ListView listView = (ListView) findViewById(R.id.listview);          myRefreshListView.setListView(listView);          listView.setAdapter(adapter);            // 设置进度条的颜色变化,最多可以设置4种颜色     myRefreshListView.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_green_light,                  android.R.color.holo_orange_light, android.R.color.holo_red_light);          // 设置下拉刷新监听器          myRefreshListView.setOnRefreshListener( new OnRefreshListener() {                @Override              public void onRefresh() {                  Toast.makeText(MainActivity. this , "refresh" , Toast.LENGTH_SHORT).show();                  myRefreshListView.postDelayed( new Runnable() {                        @Override                      public void run() {                          // 更新完后调用该方法结束刷新                          myRefreshListView.setRefreshing( false );                            adapter.getData().clear();                          // 模拟一些数据                          for ( int i = 0 ; i < 20 ; i++) {                              adapter.addData( "liu hhh " + i);                          }                      }                  }, 1000 );              }          });            // 加载监听器          myRefreshListView.setOnLoadListener( new OnLoadListener() {                @Override              public void onLoad() {                  myRefreshListView.postDelayed( new Runnable() {                      @Override                      public void run() {                          // 加载完后调用该方法                          adapter.addData( new Date().toGMTString());                          adapter.notifyDataSetChanged();                          myRefreshListView.setLoading( false );                      }                  }, 1500 );              }          });      }        class mydapter extends BaseAdapter {          List datas = new ArrayList();            public mydapter() {              // 模拟一些数据              for ( int i = 0 ; i < 20 ; i++) {                  datas.add( "item - " + i);              }          }            public void setData(List data) {              this .datas = data;              notifyDataSetChanged();          }            public void addData(String str) {              this .datas.add(str);              notifyDataSetChanged();          }            public List getData() {              return datas;          }            @Override          public int getCount() {              return datas.size();          }            @Override          public Object getItem( int position) {              return datas.get(position);          }            @Override          public long getItemId( int position) {              return position;          }            @Override          public View getView( int position, View convertView, ViewGroup parent) {              if (convertView == null ) {                  convertView = MainActivity. this .getLayoutInflater().inflate(R.layout.item, null );              }                TextView tv = (TextView) convertView.findViewById(R.id.text);              tv.setText(datas.get(position));                return convertView;          }      } }

listView_footer:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <? xml version="1.0" encoding="utf-8"?> < RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="fill_parent"      android:layout_height="wrap_content"      android:background="@color/very_light_gray"      android:gravity="center"      android:layout_gravity="center_horizontal"      android:paddingBottom="10dip"      android:paddingTop="10dip" >        < ProgressBar          android:id="@+id/pull_to_refresh_load_progress"          style="@android:style/Widget.ProgressBar.Small.Inverse"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_centerHorizontal="true"          android:layout_centerVertical="true"          android:indeterminate="true"          android:paddingRight="10dp" />        < TextView          android:id="@+id/pull_to_refresh_loadmore_text"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:gravity="center_vertical"          android:layout_toRightOf="@+id/pull_to_refresh_load_progress"          android:paddingTop="5dip"          android:text="@string/loading"          android:textAppearance="?android:attr/textAppearanceMedium"          android:textColor="@android:color/darker_gray"          android:textSize="14sp"          android:textStyle="bold" />   RelativeLayout >

main.xml

1 2 3 4 5 6 7 8 9 10 11 12 13 <? xml version="1.0" encoding="utf-8"?> < com.example.demo.mySwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:id="@+id/swipe_layout"      android:layout_width="match_parent"      android:layout_height="match_parent" >        < ListView          android:id="@+id/listview"          android:layout_width="match_parent"          android:layout_height="match_parent" >      ListView >   com.example.demo.mySwipeRefreshLayout >

item.xml:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <? xml version="1.0" encoding="utf-8"?> < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical" >        < TextView          android:id="@+id/text"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:gravity="left"          android:padding="10dp"          android:text="wo lai le"          android:background="@color/very_light_gray"/>            < View          android:layout_width="match_parent"          android:layout_height="1dp"          android:background="@android:color/white"/>   LinearLayout >

 

参考链接

http://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html

 

版权所有,转载须注明作者(金田)及出处(原文)

更多相关文章

  1. 加载一张高德地图
  2. android 使用butterknife简化加载布局控件
  3. Android(安卓)上显示 PDF 文件
  4. Android中关于Volley的使用(二)加载Json数据
  5. Android中BaseFragment封装多状态视图显示
  6. android listview 实现从数据库读取已读功能,服务器通知增加,刷新l
  7. Tablayout+Viewpager+Fragment组合使用以及懒加载机制
  8. Android四种加载方式
  9. 自定义Spinner下拉列表

随机推荐

  1. Android 防止设备休眠
  2. Android 判断手势的滑动方向
  3. Android Room,编译成功,倒是 build APK 失
  4. [置顶] Android中图像变换Matrix的原理应
  5. 还在用递归删除文件夹及里面的文件吗?andr
  6. 导入Android工程源码出现乱码问题的解决
  7. Android 网络通信框架Volley简介
  8. android 画图-----直接引用图像
  9. Android样式与主题
  10. 【framework】EventLog分析