前言:众所周知ListView这个控件是安卓中常用而又难用的控件,其分页功能也是我们在app中常见的功能,本篇详细讲解其分页的实现(建议对listview的adapter有些了解,以及java基础的面向对象及接口的实现类有些了解的在看本篇)。
一 首先看下篇章结构:
(为了逻辑清晰 方便阅读)
二 基本思路实现(后面附代码及详细注释)
1 activity_main.xml中创建ListView(此处先建立ListView)
2 MainActivity中先实现ListView要展示的界面(效果如下)
其中QQ为javaBean封装的字段(就封装这一个字段)
图片 按钮 直接是通过adapter加载xml视图填充的
3 实现了上面的布局后修改ListView :
自定义类(LoadFootListView )继承ListView 实现主要方法(添加底部布局View)
然后把前面的ListView修改为自定义的ListView
4 自定义类中滑动事件的监听实现 自定义类中调用MainActivity中数据(接口的回调)
三 代码实现
1 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.listviewdividepage.MainActivity">
<com.example.administrator.listviewdividepage.LoadFootListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv_list">
</com.example.administrator.listviewdividepage.LoadFootListView>
</LinearLayout>
2 MainActivity
package com.example.administrator.listviewdividepage;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import com.example.administrator.listviewdividepage.Adapters.MyListViewBaseAdapter;
import com.example.administrator.listviewdividepage.JavaBeans.QQDesc;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements LoadFootListView.ILoadListener {
private LoadFootListView lvList;//listview 控件
private List<QQDesc> qqList;//集合
private MyListViewBaseAdapter adapter = null;//数据适配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
qqList = new ArrayList<QQDesc>();// 初始化集合
initListView();
}
private void initListView() {
// 先在集合中加入6条数据
for (int i = 0; i < 6; i++) {
QQDesc qqDesc = new QQDesc();
qqDesc.setName("QQ");
qqList.add(qqDesc);
}
if (adapter == null) {
lvList = (LoadFootListView) findViewById(R.id.lv_list);
lvList.setInterface(this);
adapter = new MyListViewBaseAdapter(this, qqList);
lvList.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
}
/* 接口的方法 */
@Override
public void onLoad() {
//1加载更多数据 通知listView显示数据
// 为了能看见效果个两秒后加载数据
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
QQDesc qqDesc = new QQDesc();
qqDesc.setName("QQ");
qqList.add(qqDesc);
}
if (adapter == null) {
lvList = (LoadFootListView) findViewById(R.id.lv_list);
lvList.setInterface(MainActivity.this);
adapter = new MyListViewBaseAdapter(MainActivity.this, qqList);
lvList.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
lvList.lodaComplete();// 加载完毕隐藏view
}
}
},2000);
}
};
3 自定义ListView(LoadFootListView)
package com.example.administrator.listviewdividepage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
/**
* Created by Administrator on 2017/11/28.
* 自定义ListView 实现底部分页加载
* 1 吧底部加载的布局View加入listView
* 2 滑动事件的监听(listView实现滑动监听接口)
*/
public class LoadFootListView extends ListView implements AbsListView.OnScrollListener{
private int totalItemCount;//当前总条目
private int lastVisibleItem;//最后一个可见条目
private View mView;//底部布局的View
private boolean isLoading=false;//加载判断
private ILoadListener iLoadListener;//接口实现类
public LoadFootListView(Context context) {
super(context);
initFootLoad(context);
}
public LoadFootListView(Context context, AttributeSet attrs) {
super(context, attrs);
initFootLoad(context);
}
public LoadFootListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initFootLoad(context);
}
// 初始化分页加载
public void initFootLoad(Context context){
mView = View.inflate(context, R.layout.foot_item,null);
// 吧定义好的view 放入listView底部
this.addFooterView(mView);
// 设置滚动事件的监听
this.setOnScrollListener(this);
// 初始的时候隐藏
mView.findViewById(R.id.load_more).setVisibility(View.GONE);
}
/* 接口的两个滑动方法*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 进行底部判断 (划到底部 切停止滑动)
if(lastVisibleItem==totalItemCount&&scrollState==SCROLL_STATE_IDLE){
// 加载更多新的数据(MainActivity中的数据)
// 加载数据之前进行显示加载布局
if(!isLoading){
isLoading = true;
mView.findViewById(R.id.load_more).setVisibility(View.VISIBLE);
//加载更多(加载MainActivity中的数据 接口回调)
iLoadListener.onLoad();//接口实现类加载函数实先 方法
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
/* 最后一个可见的条目为: 第一个可见的+ 可见的条目个数*/
this.lastVisibleItem = firstVisibleItem+visibleItemCount;
/* 滑到底部的时候的值*/
this.totalItemCount=totalItemCount;
//通过以上两个值判断是否滑到底部
}
/* 加载更多数据的回调接口
* 在其他的类中实现就行了 本类中使用接口(设置接口使用函数)
* */
public void setInterface(ILoadListener iLoadListener){
//通过外面的接口实现类调用此函数 传进来实现类对象
this.iLoadListener=iLoadListener;
}
public interface ILoadListener{
public void onLoad();
}
public void lodaComplete(){
isLoading=false;
mView.findViewById(R.id.load_more).setVisibility(View.GONE);
}
}
4 adapter的实现(MyListViewBaseAdapter)
package com.example.administrator.listviewdividepage.Adapters;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.example.administrator.listviewdividepage.JavaBeans.QQDesc;
import com.example.administrator.listviewdividepage.R;
import java.util.List;
import java.util.Objects;
/**
* Created by Administrator on 2017/11/28.
*/
public class MyListViewBaseAdapter extends BaseAdapter {
/* 由于下面需要 上下文 集合 故在此处声明*/
private Context context;
private List<QQDesc>qqList;
public MyListViewBaseAdapter(Context context,List<QQDesc>qqList){
this.context= context;
this.qqList=qqList;
}
@Override
public int getCount() {
return qqList.size();
}
@Override
public QQDesc getItem(int position) {
return qqList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/* 简单的优化*/
View view = null;
if (convertView==null){
view = View.inflate(context, R.layout.myadapter_item,null);
TextView tvName= (TextView) view.findViewById(R.id.tv_name);
tvName.setText(qqList.get(position).getName());
}else{
view=convertView;
}
return view;
}
}
5 java bean
package com.example.administrator.listviewdividepage.JavaBeans;
/**
* Created by Administrator on 2017/11/28.
*/
public class QQDesc {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
6 foot_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:gravity="center"
android:id="@+id/load_more">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:textSize="20sp"
android:textColor="@color/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Loading..."/>
</LinearLayout>
7 listView的布局页面(adapter填充)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_gravity="center"
android:textSize="20sp"
android:textColor="@color/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="名字"/>
<Button
android:id="@+id/btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="立刻下载"/>
</LinearLayout>
</LinearLayout>
效果:
由于过程比较繁琐建议看不懂的吧代码全部粘贴自己建立工程分析代码(有详细注释)
小结:难点在于滑动到底部的判断以及接口的回调。