转载请注明出处:http://blog.csdn.net/droyon/article/details/9102797
源代码请从官方网站下载,本文针对源代码增加上自己的理解。
package com.android.contacts.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* A ListView that can be asked to scroll (smoothly or otherwise) to a specific
* position. This class takes advantage of similar functionality that exists
* in {@link ListView} and enhances it.
* 联系人应用中自定义组件,增强了ListView的功能。
* 用于滑动到某一个位置 以及 在到达某个位置时是否平滑
*/
public class AutoScrollListView extends ListView {
/**
* Position the element at about 1/3 of the list height
*/
private static final float PREFERRED_SELECTION_OFFSET_FROM_TOP = 0.33f;
private int mRequestedScrollPosition = -1;
private boolean mSmoothScrollRequested;
public AutoScrollListView(Context context) {
super(context);
}
public AutoScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Brings the specified position to view by optionally performing a jump-scroll maneuver:
* first it jumps to some position near the one requested and then does a smooth
* scroll to the requested position. This creates an impression of full smooth
* scrolling without actually traversing the entire list. If smooth scrolling is
* not requested, instantly positions the requested item at a preferred offset.
* 提供的一个方法,是否平滑滑动到position处
*/
public void requestPositionToScreen(int position, boolean smoothScroll) {
mRequestedScrollPosition = position;
mSmoothScrollRequested = smoothScroll;
requestLayout();
}
/**
* 这个方法在ListView(ListView包含了一系列的Item【项】)中用于布局ListViewItem。
*/
@Override
protected void layoutChildren() {//重写的ListView中的方法,这个方法,主要就是封装了ListView中的layoutChildren。
super.layoutChildren();
if (mRequestedScrollPosition == -1) {
return;
}
final int position = mRequestedScrollPosition;
mRequestedScrollPosition = -1;
int firstPosition = getFirstVisiblePosition() + 1;
int lastPosition = getLastVisiblePosition();
if (position >= firstPosition && position <= lastPosition) {
return; // Already on screen
}
final int offset = (int) (getHeight() * PREFERRED_SELECTION_OFFSET_FROM_TOP);
if (!mSmoothScrollRequested) {
setSelectionFromTop(position, offset);
// Since we have changed the scrolling position, we need to redo child layout
// Calling "requestLayout" in the middle of a layout pass has no effect,
// so we call layoutChildren explicitly
//如果不需要平滑的滑动到position处,直接调用父类的layoutChildren方法。
super.layoutChildren();
} else {
// We will first position the list a couple of screens before or after
// the new selection and then scroll smoothly to it.
//现在是处理平滑滑动到某个位置了,如何处理那?
//我们首先需要将当前的list条目焦点设定在离要滑动的位置2屏内。为什么这么处理那?
//设想一下,list有1000个条目,一屏可以存放10条条目,我们当前处在最后一屏(也就是当前显示990~1000),那么我们要平滑滑动的位置为1
//我们的listView要从990一直平滑滑动到1,这要多费功夫,
//所以,直接把焦点设定在list的20处(2屏数目),然后从20位置平滑过度到1。
int twoScreens = (lastPosition - firstPosition) * 2;
int preliminaryPosition;
if (position < firstPosition) {
preliminaryPosition = position + twoScreens;
if (preliminaryPosition >= getCount()) {
preliminaryPosition = getCount() - 1;
}
if (preliminaryPosition < firstPosition) {
setSelection(preliminaryPosition);
super.layoutChildren();
}
} else {
preliminaryPosition = position - twoScreens;
if (preliminaryPosition < 0) {
preliminaryPosition = 0;
}
if (preliminaryPosition > lastPosition) {
setSelection(preliminaryPosition);
super.layoutChildren();
}
}
smoothScrollToPositionFromTop(position, offset);
}
}
}