Android实现listview的上拉加载更多
当前实例为最基本的上拉加载实现, 学习者可根据逻辑自创建...
实现逻辑:
1、创建自定义ListView,并且监听其滚动的事件
2、自定义ListView的类中应实现一个内部接口,用来实现加载更多数据的逻辑
3、使用该listview,且在引用类中实现加载更多数据的内部接口
4、(最好自定义Adapter)
最终效果
下图为最基本的项目结构:
以下为每一个步骤的详解:
1、创建自定义ListView,并且监听其滚动的事件
继承ListView:下拉的时候需要动态的加载一个布局文件提示给用户,告知我们现在正在帮您刷新数据 。
实现OnScrollListener: 只有在第一个item为最顶部的时候才开始进行我们的‘下拉加载’更多的代码逻辑,需要程序员知道我们现在能否进行触发该逻辑代码
1.1 类属性的声明
private int firstVisibleItem; // 表示当前listview是否在第一行
private View v; // 提示的加载布局
private IReflashListener iReflashListener; // 实现刷新的内部接口
1.2 类初始化
public MyListView(Context context) {
super(context, null);
init();
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setOnScrollListener(this);
}
1.3 对其OnScrollListener的方法实现
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
/**
* firstVisibleItem==0: 表示在第一个Item项
* scrollState!=0: 该listview正在移动
*/
if (firstVisibleItem == 0 && scrollState != 0) {
// 进行添加顶部布局
v = LayoutInflater.from(getContext()).inflate(R.layout.item_top_layout, null);
this.addHeaderView(v);
if (iReflashListener != null)
iReflashListener.onReflash(); // 加载数据
} else {
if (v != null) {
// 隐藏顶部布局
this.removeHeaderView(v);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}
动态加载数据的操作放在
onScrollStateChanged中的原因:只有用户在滚动该listview的时候才能进行加载数据。
onScroll方法中的firstVisibleItem: 当前listview的操作缓存中的第一条item是该数据源的第几条。
2、自定义ListView的类中应实现一个内部接口,用来实现加载更多数据的逻辑
以上的内容基本上已经实现了该上拉刷新的功能。
3、动态布局的创建
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/seekBar"
style="@android:style/Widget.ProgressBar.Small" />
<TextView android:text="下拉加载"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
将该组件放在任意的layout中即可。
4、使用该listview,且在引用类中实现加载更多数据的内部接口
稍微值得注意的是,在我们listview的引用文件中,该组件需要使用以下方式
<com.example.administrator.listviewautoload.MyListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
此方式为使用自定义组件。
5、adapter实现
在该listview中,建议使用自定义adapter。(或者可以说任何listview都建议使用自定义adapter)
adapter大家都用过不少了,就直接将adapter源码贴出
package com.example.administrator.listviewautoload;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
/**
* 进行数据与listview的绑定
*/
public class MyAdapter extends BaseAdapter {
private List<String> lists; // item总数据
private Context context; // 上下文(此处级别因为activity)
private ViewHolder viewHolder;
private boolean flag; // 是否可以加载更多
public MyAdapter(List<String> lists, Context context) {
this.lists = lists;
this.context = context;
}
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return lists.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/**
* 做出一定的listview优化
*/
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
viewHolder = new ViewHolder();
viewHolder.textView = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(lists.get(position));
return convertView;
}
class ViewHolder {
TextView textView;
}
}
这个adapter还是非常简单的,内部定义了一个ViewHolder类。 包含了一个listview item的组件。使用此种getView方法方式可以最优化的帮组我们节省Android内存(建议使用)。
最后一步,那就是动态的添加数据
现为listview绑定一个数据适配器
在该类中,我们需要实现该listview的动态加载数据接口
public class MainActivity extends Activity implements MyListView.IReflashListener
我们实现它的方法,在该方法中就可以调用自己特有的加载数据方法,只要放入到adapter的数据源中,调用adapte的notifyDataSetChanged即可
(notifyDataSetChanged: 通知进行适配的Adapter, 表示这个数据源的数据已经更新了,你现在要在主界面中同时做出刷新 )
@Override
public void onReflash() {
Toast.makeText(this, "MainActivity onReflash", Toast.LENGTH_SHORT).show();
/**
* 开始加载刷新的数据(此为模拟动态加载出来的数据)
*/
for (int i = 0; i < 2; i++) {
lists.add(Integer.valueOf(lists.get(lists.size() - 1)) + 1 + "");
}
adapter.notifyDataSetChanged();
}
至此,我们的功能就基本实现了,有木有特别简单。 因仔细注意MainActivity的init方法中listview.setiReflashListener(this) ;
这句代码一定要有, 否则在listview中就不能实现动态加载了。
这是笔者的第一篇博客,可能讲的不是很详细,但代码几乎全部都贴出来了。 学习者们应该很容易理解。