OnScrollListener接口是定义在AbsListView中的,而AbsListView的直接子类有和,非直接子类有。OnScrollListener的完整路径是frameworks\base\core\java\android\widget\AbsListView.java,代码如下:
/** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. */ public interface OnScrollListener { /** * The view is not scrolling. Note navigating the list using the trackball counts as * being in the idle state since these transitions are not animated. */ public static int SCROLL_STATE_IDLE = 0; /** * The user is scrolling using touch, and their finger is still on the screen */ public static int SCROLL_STATE_TOUCH_SCROLL = 1; /** * The user had previously been scrolling using touch and had performed a fling. The * animation is now coasting to a stop */ public static int SCROLL_STATE_FLING = 2; /** * Callback method to be invoked while the list view or grid view is being scrolled. If the * view is being scrolled, this method will be called before the next frame of the scroll is * rendered. In particular, it will be called before any calls to * {@link Adapter#getView(int, View, ViewGroup)}. * * @param view The view whose scroll state is being reported * * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE}, * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}. */ public void onScrollStateChanged(AbsListView view, int scrollState); /** * Callback method to be invoked when the list or grid has been scrolled. This will be * called after the scroll has completed * @param view The view whose scroll state is being reported * @param firstVisibleItem the index of the first visible cell (ignore if * visibleItemCount == 0) * @param visibleItemCount the number of visible cells * @param totalItemCount the number of items in the list adaptor */ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount); } 该接口定义了三种滚动状态和两个回调函数,下面的代码使用onScroll来实现滚屏时提示内容首字母功能,当然,重点在例子的实现分析上面,并不局限于onScroll的使用。直接先看MainActivity的实现吧:(代码来自APIDemos,有修改) package hust.iprai.asce1885; import android.app.ListActivity; import android.content.Context; import android.graphics.PixelFormat; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.ViewGroup.LayoutParams; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ArrayAdapter; import android.widget.TextView; /** * 直接继承ListActivity,免去了ListView的继承,同时实现OnScrollListener接口 * */ public class MainActivity extends ListActivity implements OnScrollListener { private final class RemoveWindow implements Runnable { public void run() { removeWindow(); } } private RemoveWindow mRemoveWindow = new RemoveWindow(); Handler mHandler = new Handler(); private WindowManager mWindowManager; private TextView mDialogText; private boolean mShowing; //是否显示mDialogText private boolean mReady; //mDialogText是否已准备好 private char mPrevLetter = Character.MIN_VALUE; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //获取Window窗口管理服务 mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); //使用ArrayAdapter将字符串数组中的数据映射到TextView中 setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings)); //设置滚动监听器ScrossListener getListView().setOnScrollListener(this); //获取LayoutInflater服务 LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); //从xml文件生成TextView对象 mDialogText = (TextView) inflate.inflate(R.layout.list_position, null); mDialogText.setVisibility(View.INVISIBLE); //将Runnable添加到消息队列中 mHandler.post(new Runnable() { public void run() { mReady = true; //设置mDialogText的WindowManager.LayoutParams参数 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mWindowManager.addView(mDialogText, lp); } }); } @Override protected void onDestroy() { super.onDestroy(); mWindowManager.removeView(mDialogText); mReady = false; } @Override protected void onPause() { super.onPause(); removeWindow(); mReady = false; } @Override protected void onResume() { super.onResume(); mReady = true; } //OnScrollListener的回调函数 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (mReady) { //取得当前ListView中第一项内容的首字母 char firstLetter = mStrings[firstVisibleItem].charAt(0); //当mDialogText还不可见且当前首字母于前次滚动后首字母不一致时 //将mDialogText设置为可见 if (!mShowing && firstLetter != mPrevLetter) { mShowing = true; mDialogText.setVisibility(View.VISIBLE); } //将首字母显示出来 mDialogText.setText(((Character)firstLetter).toString()); //将消息队列中还在等待post的mRemoveWindow清除 mHandler.removeCallbacks(mRemoveWindow); //将Runnable mRemoveWindow添加到消息队列中,并延迟3s后运行 //实现的功能就是在mDialogText显示3s后,将它设置为不可见 mHandler.postDelayed(mRemoveWindow, 3000); mPrevLetter = firstLetter; } } //OnScrollListener的回调函数 public void onScrollStateChanged(AbsListView view, int scrollState) { } //将mDialogText设置为不可见 private void removeWindow() { if (mShowing) { mShowing = false; mDialogText.setVisibility(View.INVISIBLE); } } //用于显示的模拟数据 private String[] mStrings = Cheeses.sCheeseStrings; } mDialogText的布局文件list_position.xml如下:<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:textSize="50sp" android:textColor="#99FFFFFF" android:typeface="monospace" android:background="#BB000000" android:minWidth="70dip" android:maxWidth="70dip" android:padding="10dip" android:gravity="center" /> 程序运行结果如下图所示: