前面说过了ListView的下拉刷新效果,有些时候我们需要让ListView在滑动到最底部时,自动去向服务器请求下一页数据。这时候就需要监听的ListView的滑动状态了。
mListView.setOnScrollListener(OnScrollListener l);
OnScrollListener 内部有3个常量来记录ListView的滚动状态
int SCROLL_STATE_FLING The user had previously been scrolling using touch and had performed a fling.
int SCROLL_STATE_IDLE The view is not scrolling.
int SCROLL_STATE_TOUCH_SCROLL The user is scrolling using touch, and their finger is still on the screen
知道这些常量代表的含义,我们就可以很轻松的实现 滚动翻页的效果了。
footer_more.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" android:orientation="horizontal" android:padding="15dp" > <ProgressBar android:id="@+id/pb_load_progress" style="@android:style/Widget.ProgressBar.Small.Inverse" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:indeterminate="true"> </ProgressBar> <TextView android:id="@+id/tv_load_more" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10.0dp" android:gravity="center" android:text="@string/load_more_data" android:textColor="@color/black" > </TextView> </LinearLayout>
<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" tools:context=".MainActivity" > <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:text="@string/load_more" android:textSize="15sp" /> <ListView android:id="@+id/mListView" android:layout_below="@id/tv_title" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/transparent" /> </RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/iv_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/app_name" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/iv_icon" android:textSize="18sp" android:textColor="@color/black"/> <TextView android:id="@+id/tv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/iv_icon" android:layout_below="@id/tv_title" android:layout_marginTop="5dp" android:textSize="15sp" android:textColor="@color/black"/> </RelativeLayout>
package com.example.loadmore; import java.util.ArrayList; import java.util.List; import com.example.loadmore.entity.DataNews; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends Activity implements OnScrollListener { private static final int LOAD_DATA_FINISH = 1; private static final String TAG = MainActivity.class.getName(); private List<DataNews> dataList = new ArrayList<DataNews>(); private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case LOAD_DATA_FINISH: tv_load_more.setText(R.string.load_more_data); pb_load_progress.setVisibility(View.GONE); if(mAdapter!=null){ mAdapter.notifyDataSetChanged(); } break; default: break; } }; }; private int startIndex = 0; private int requestSize = 10; private ListView mListView; private View moreView; private DataAdapter mAdapter; private int lastItem; private TextView tv_load_more; private ProgressBar pb_load_progress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findView(); setListener(); } private void findView() { LayoutInflater inflater = LayoutInflater.from(getApplicationContext()); moreView = inflater.inflate(R.layout.footer_more, null); tv_load_more = (TextView) moreView.findViewById(R.id.tv_load_more); pb_load_progress = (ProgressBar) moreView.findViewById(R.id.pb_load_progress); mListView = (ListView) findViewById(R.id.mListView); for (int i = 0; i < 10; i++) { DataNews dn = new DataNews(); dn.setTitle("第 " + i + " 行标题"); dn.setContent("" + i + " 行内容"); dataList.add(dn); } mListView.addFooterView(moreView); mAdapter = new DataAdapter(getApplicationContext()); mListView.setAdapter(mAdapter); } private void setListener() { mListView.setOnScrollListener(this); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { lastItem = firstVisibleItem + visibleItemCount - 1; // Log.i(TAG, // "firstVisibleItem:"+firstVisibleItem+"visibleItemCount:"+visibleItemCount+" lastItem:"+lastItem); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (lastItem == mAdapter.getCount() && scrollState == OnScrollListener.SCROLL_STATE_IDLE) { Log.e(TAG, "load more"); startIndex += requestSize; loadMoreData(); } } private void loadMoreData() { tv_load_more.setText(R.string.loading_data); pb_load_progress.setVisibility(View.VISIBLE); new Thread(){ public void run() { if (startIndex + requestSize <50) { for (int i = startIndex; i < startIndex + requestSize; i++) { DataNews dn = new DataNews(); dn.setTitle("增加 第 " + i + " 行标题"); dn.setContent("增加 第 " + i + " 行内容"); dataList.add(dn); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(LOAD_DATA_FINISH); }else{ handler.postDelayed(new Runnable() { @Override public void run() { tv_load_more.setText(R.string.no_more_data); pb_load_progress.setVisibility(View.GONE); } }, 1000); } }; }.start(); } private class DataAdapter extends BaseAdapter { private Context ctx; private LayoutInflater inflater; public DataAdapter(Context ctx) { this.ctx = ctx; inflater = LayoutInflater.from(ctx); } @Override public int getCount() { return dataList == null ? 0 : dataList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return dataList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.list_item, null); holder = new ViewHolder(); holder.tv_title = (TextView) convertView .findViewById(R.id.tv_title); holder.tv_content = (TextView) convertView .findViewById(R.id.tv_content); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } DataNews dn = dataList.get(position); holder.tv_title.setText(dn.getTitle()); holder.tv_content.setText(dn.getContent()); return convertView; } } static class ViewHolder { public TextView tv_title; public TextView tv_content; } }
运行效果截图
正常状态时
滚动到底部时
没有更多数据时