android-----ListView上拉加载更多实现

12人阅读 评论(0) 收藏 举报
分类:

    前几篇博客,我们从缓存的角度优化了ListView,如果你对此还不太熟悉的话可以到android-----带你一步一步优化ListView(一)android-----带你一步一步优化ListView(二)android-----带你一步一步优化ListView(三),查看,其实,对于ListView的优化来说,还有一种方式我们没有涉及,那就是分页加载了,你在微信加载朋友圈的时候会发现每次显示到最下面会出现加载更多的提示信息,这就是分页加载的使用啦,我们没有必要每次加载ListView的数据时把所有数据全部都查找到,因为ListView本身能够显示在一个界面的条目数是有限的,我们完全可以只去查找一屏幕的数据并且显示他,当用户滑动到最下面的时候再去加载下一屏幕的数据,这对于ListView上面有图片显示的应用来说优化效果特别明显,那么这篇博客,我们将会实现类似于朋友圈上拉加载更多的功能;

        先来看看效果图:

                                             

        好了,接下来我们从代码层面来讲解该怎么实现:

        首先定义一个主界面布局listview.xml

[java] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.     <ListView   
  7.         android:id="@+id/listView"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent">  
  10.     </ListView>  
  11. </LinearLayout>  
        定义每个item的显示布局item.xml
[java] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.     <ImageView  
  7.         android:id="@+id/imageView"  
  8.         android:layout_width="50dp"  
  9.         android:layout_height="50dp"  
  10.         />  
  11.     <TextView  
  12.         android:id="@+id/textView"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="50dp"  
  15.         android:layout_toRightOf="@id/imageView"  
  16.         android:layout_marginTop="20dp"  
  17.         android:layout_marginRight="70dp"  
  18.         />  
  19. </RelativeLayout>  
        很简单,就是一个ImageView和一个TextView

        接下来就是一个用于显示加载更多的布局了load_more.xml

[java] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/loadmore"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:gravity="center"    
  7.     android:orientation="horizontal" >  
  8.       
  9.     <ProgressBar    
  10.         android:id="@+id/progress"    
  11.         style="?android:attr/progressBarStyleSmall"    
  12.         android:layout_width="wrap_content"    
  13.         android:layout_height="wrap_content"    
  14.         android:layout_marginBottom="30dp"    
  15.         android:layout_marginTop="30dp" />    
  16.     
  17.     <TextView    
  18.         android:id="@+id/tv"    
  19.         android:layout_width="wrap_content"    
  20.         android:layout_height="wrap_content"    
  21.         android:layout_marginLeft="20dp"    
  22.         android:text="正在加载..."    
  23.         android:textColor="#FF0000" />  
  24. </LinearLayout>  
        这个界面中会显示一个进度条和正在加载的TextView

        之后便是为我们的ListView设置适配器ListViewAdapter了

[java] view plain copy
  1. public class ListViewAdapter extends BaseAdapter{  
  2.       
  3.     public List<String> list;  
  4.     public LayoutInflater inflater;  
  5.       
  6.       
  7.     public ListViewAdapter() {  
  8.     }  
  9.       
  10.     public ListViewAdapter(Context context,List<String> list) {  
  11.         this.list = list;  
  12.         this.inflater = LayoutInflater.from(context);  
  13.     }  
  14.       
  15.     @Override  
  16.     public int getCount() {  
  17.         return list.size();  
  18.     }  
  19.   
  20.     @Override  
  21.     public String getItem(int position) {  
  22.         return list.get(position);  
  23.     }  
  24.   
  25.     @Override  
  26.     public long getItemId(int position) {  
  27.         return 0;  
  28.     }  
  29.       
  30.     public void updateView(List<String> nowList)  
  31.     {  
  32.         this.list = nowList;  
  33.         this.notifyDataSetChanged();//强制动态刷新数据进而调用getView方法  
  34.     }  
  35.     @Override  
  36.     public View getView(int position, View convertView, ViewGroup parent) {  
  37.         View view = null;  
  38.         ViewHolder holder = null;  
  39.         if(convertView == null)  
  40.         {  
  41.             view = inflater.inflate(R.layout.item, null);  
  42.             holder = new ViewHolder();  
  43.             holder.imageView = (ImageView)view.findViewById(R.id.imageView);  
  44.             holder.textView = (TextView)view.findViewById(R.id.textView);  
  45.             view.setTag(holder);//为了复用holder  
  46.         }else  
  47.         {  
  48.             view = convertView;  
  49.             holder = (ViewHolder) view.getTag();  
  50.         }  
  51.         holder.imageView.setImageResource(R.drawable.image);  
  52.         holder.textView.setText(list.get(position));  
  53.         return view;  
  54.     }     
  55.     static class ViewHolder  
  56.     {  
  57.         ImageView imageView;  
  58.         TextView textView;  
  59.     }  
  60. }  

        这段代码中的getView方法就是我们平常使用ListView为其设置适配器所要重写的方法,重点在于第30行的updateView方法了,这个方法用于修改需要显示在ListView上面的数据信息,并且随后调用notifyDataSetChanged方法来通知适配器告诉他ListView上面需要显示的内容已经发生了改变,这时候就会调用getView方法来重新加载数据了;

        接下来就是我们的主Activity

[java] view plain copy
  1. public class MainActivity extends Activity implements OnScrollListener{  
  2.   
  3.     public View loadmoreView;  
  4.     public LayoutInflater inflater;  
  5.     public ListView listView;  
  6.     public int last_index;  
  7.     public int total_index;  
  8.     public List<String> firstList = new ArrayList<String>();//表示首次加载的list  
  9.     public List<String> nextList = new ArrayList<String>();//表示出现刷新之后需要显示的list  
  10.     public boolean isLoading = false;//表示是否正处于加载状态  
  11.     public ListViewAdapter adapter;  
  12.       
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.listview);  
  17.         inflater = LayoutInflater.from(this);  
  18.         loadmoreView = inflater.inflate(R.layout.load_more, null);//获得刷新视图  
  19.         loadmoreView.setVisibility(View.VISIBLE);//设置刷新视图默认情况下是不可见的  
  20.         listView = (ListView) findViewById(R.id.listView);  
  21.         initList(1010);  
  22.         adapter = new ListViewAdapter(this, firstList);  
  23.         listView.setOnScrollListener(this);  
  24.         listView.addFooterView(loadmoreView,null,false);  
  25.         listView.setAdapter(adapter);  
  26.     }  
  27.     /** 
  28.      * 初始化我们需要加载的数据 
  29.      * @param firstCount 
  30.      * @param nextCount 
  31.      */  
  32.     public void initList(int firstCount,int nextCount)  
  33.     {  
  34.         for(int i = 0;i < firstCount;i++)  
  35.         {  
  36.             firstList.add("第"+(i+1)+"个开始加载");  
  37.         }  
  38.         for(int i = 0;i < firstCount;i++)  
  39.         {  
  40.             nextList.add("第"+(i+1)+"个开始加载");  
  41.         }  
  42.         for(int i = 0;i < nextCount;i++)  
  43.         {  
  44.             nextList.add("刷新之后第"+(i+1)+"个开始加载");  
  45.         }  
  46.     }  
  47.     @Override  
  48.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
  49.         last_index = firstVisibleItem+visibleItemCount;  
  50.         total_index = totalItemCount;  
  51.         System.out.println("last:  "+last_index);  
  52.         System.out.println("total:  "+total_index);  
  53.     }  
  54.   
  55.     @Override  
  56.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  57.         if(last_index == total_index && (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE))  
  58.         {  
  59.             //表示此时需要显示刷新视图界面进行新数据的加载(要等滑动停止)  
  60.             if(!isLoading)  
  61.             {  
  62.                 //不处于加载状态的话对其进行加载  
  63.                 isLoading = true;  
  64.                 //设置刷新界面可见  
  65.                 loadmoreView.setVisibility(View.VISIBLE);  
  66.                 onLoad();  
  67.             }  
  68.         }  
  69.     }  
  70.       
  71.     /** 
  72.      * 刷新加载 
  73.      */  
  74.     public void onLoad()  
  75.     {  
  76.         try {  
  77.             //模拟耗时操作  
  78.             Thread.sleep(2000);  
  79.         } catch (InterruptedException e) {  
  80.             e.printStackTrace();  
  81.         }  
  82.         if(adapter == null)  
  83.         {  
  84.             adapter = new ListViewAdapter(this, firstList);  
  85.             listView.setAdapter(adapter);  
  86.         }else  
  87.         {  
  88.             adapter.updateView(nextList);  
  89.         }  
  90.         loadComplete();//刷新结束  
  91.     }  
  92.       
  93.     /** 
  94.      * 加载完成 
  95.      */  
  96.     public void loadComplete()  
  97.     {  
  98.         loadmoreView.setVisibility(View.GONE);//设置刷新界面不可见  
  99.         isLoading = false;//设置正在刷新标志位false  
  100.         MainActivity.this.invalidateOptionsMenu();  
  101.         listView.removeFooterView(loadmoreView);//如果是最后一页的话,则将其从ListView中移出  
  102.     }  
  103. }  

        在第19行获得了加载更多的刷新视图并且第20行设置该视图是可见的,因为我们模拟的是要加载两页的数据,这样的话第一页加载结束之后需要显示加载更多的视图,在第24行将该视图添加到了ListView的最下面,随后为Listview添加滑动事件,这里面最重要的两个方法就是第48行的onScroll和第56行的onScrollStateChanged,通过onScroll中的last_index用于获得当前页面表示在现时屏幕可以见到的最大Item的位置,total_index用于表示ListView可以加载的ListItem总数;第57行判断当前页面表示在现时屏幕可以见到的最大Item的位置如果等于ListView可以加载的ListItem总数并且滑动停止的话,则判断isLoading是否处于加载状态,如果不处于加载状态的话,则调用onLoad方法去加载,这个方法里面的Thread.sleep(2000)用于模拟耗时操作,随后利用ListAdapter的updateView方法更新ListView需要显示的数据,最后调用loadComplete来结束刷新操作,第98行设置刷新视图不可见,修改isLoading加载标志,最后将加载更多视图从当前ListView中移除;

        至此,上拉加载更多讲解结束,下一篇我们将讲解一下下拉刷新的实现,谢谢大家!

点击下载源码!!!!!
查看评论

android 开源框架之——下拉刷新,上拉加载更多总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] 最近项目中需要用到下拉刷新的功能,发现自己的写的不是很好,网上搜了一下,发现开源的框架好...
  • H_shaohui
  • H_shaohui
  • 2017-04-19 15:18:41
  • 2422

SwipeRefreshLayout+RecyclerView上拉加载,下拉刷新

  • 2018年03月23日 15:33
  • 21.26MB
  • 下载

自定义SwipeRefreshLayout实现上拉加载,下拉刷新

SwipeRefreshLayout实现上拉加载 原来的Android SDK中并没有下拉刷新组件,但是这个组件确实绝大多数APP必备的一个部件。好在google在v4包中出了一个S...
  • anshuangxin6666
  • anshuangxin6666
  • 2018-03-16 19:40:04
  • 37

Android 我关于上拉加载,下拉刷新的处理方式(可以解决viewpager)

这几天要找实习了,有时候感觉自己真的是好笨啊,明明编程了两年半,但是想想自己好像真的是什么都不会,简历不知道写什么,真的是好心塞啊。最近总是想起周星驰的一句话 ”努力,奋斗“ (出自喜剧之王)本来这一...
  • qq_32515625
  • qq_32515625
  • 2018-03-18 01:07:12
  • 124

移动端上拉刷新下拉加载框架

1.智能下拉刷新框架-SmartRefreshLayout 传送: https://github.com/scwang90/SmartRefreshLayout2.PullToRefreshAndLo...
  • zhang__ao
  • zhang__ao
  • 2018-04-16 11:44:31
  • 16

android下拉刷新上拉加载

  • 2018年04月11日 22:59
  • 6.97MB
  • 下载

Android自定义View-下拉刷新-拉到底自动加载-LoadingRefreshLayout

主要实现两个功能,第一个是  实现一个下拉加载更多的效果。第二个是RecyclerView拖动到底自动加载的效果。功能一:下拉加载更多的效果特点继承于LinearLayout,不用自己实现ViewGr...
  • Garment1991
  • Garment1991
  • 2018-04-14 17:00:04
  • 21

SmartRefreshLayout刷新控件的使用方法 (刷新加载时用GIF动画)

https://github.com/scwang90/SmartRefreshLayout 原创网址 //一个开源gif控件 compile 'pl.droidsonroids....
  • yi_199714
  • yi_199714
  • 2018-03-29 10:29:51
  • 30

XRecyclerView上啦刷新下拉加载+RxJava+Retrofit

添加依赖 compile 'com.jcodecraeer:xrecyclerview:1.5.8' compile 'com.facebook.fresco:fresco:1.3.0' //...
  • wanglinuo521
  • wanglinuo521
  • 2018-03-31 18:58:46
  • 29

android RecyclerView加载完布局后向下自动滚动了

实现一个类似朋友圈的列表,其中的九宫格图片列表用RecyclerView实现。也就是RecyclerView嵌套RecyclerView,但是出现了第一次加载完列表初始化的位置不是最上面,而是向下滚动...
  • u010523832
  • u010523832
  • 2018-04-15 00:18:13
  • 19
    个人资料
    持之以恒
    等级:
    访问量: 25万+
    积分: 1万+
    排名: 1719