ListView下拉刷新

来源:互联网 发布:天书世界太极进阶数据 编辑:程序博客网 时间:2024/06/05 17:18
ListView下拉刷新是在开发过程中经常用到的一个功能,整理如下,如果初学者有需要可以作为参考。下拉刷新头部布局如下:   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/drop_drown_list_header_padding_bottom"android:paddingTop="@dimen/drop_drown_list_header_padding_top"><!--进度条  --><ProgressBar     android:id="@+id/drop_drown_list_header_progress_bar"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    style="@style/drop_drown_list_header_progress_bar_style"    android:indeterminate="true"    android:layout_toLeftOf="@+id/drop_drown_list_header_default_text_layout"    android:visibility="gone"/><!--翻转图片  --><ImageView    android:id="@+id/drop_drown_list_header_image"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:contentDescription="@string/image_content"    android:src="@drawable/drop_down_list_arrow"    android:layout_toLeftOf="@+id/drop_drown_list_header_default_text_layout"    android:visibility="gone"/><!--文字提示  --><RelativeLayout     android:id="@+id/drop_drown_list_header_default_text_layout"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_centerHorizontal="true"    android:layout_marginLeft="10dp"    android:gravity="center">    <TextView         android:id="@+id/drop_drown_list_header_default_text"        style="@style/drop_drown_list_header_font_style"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:gravity="center"/>    <TextView         android:id="@+id/drop_down_list_header_second_text"        style="@style/drop_drown_list_header_font_style"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@+id/drop_drown_list_header_default_text"        android:gravity="center"        android:visibility="gone"/></RelativeLayout>

在布局中添加了一个ImageView用于显示下拉的箭头,一个ProgressBar正在加载时候的等待状态,两个TextView用于状态提示和显示时间接下来是在listView中添加header布局,并在onTouchEvent和滚动事件中改变header中个组件的状态和样式:public class DropDrownListView extends ListView implements OnScrollListener {private boolean isDropDrownStyle = true;private boolean hasReachedTop = false;//头部不同状态的提示文字private String headerDefaultText;private String headerPullText;private String headerReleaseText;private String headerLoadingText;private Context context;private int currentScrollState;//listView的滚动状态private int currentHeaderStatus;//头部布局的状态有四种private RelativeLayout headerLayout;private ImageView headerImage;private ProgressBar headerProgressBar;private TextView headerText;private TextView headerSecondText;//动画private RotateAnimation flipAnimation;private RotateAnimation reverseFlipAnimation;private OnScrollListener onScrollListener;private int headerReleaseMinDistance;private int headerOriginalHeight;private int headerOriginalTopPadding;private float actionDownPointY;private float headerPaaddingTopRate = 1.5f;//头部布局的四种状态public static final int HEADER_STATUS_CLICK_TO_LOAD = 1;public static final int HEADER_STATUS_DROP_DROWN_TO_LAOD = 2;public static final int HEADER_STATUS_RELEASE_TO_LOAD = 3;public static final int HEADER_STATUS_LOADING = 4;public DropDrownListView(Context context) {    super(context);    init(context);}public DropDrownListView(Context context, AttributeSet attrs) {    super(context, attrs);    getAttrs(context, attrs);    init(context);}public DropDrownListView(Context context, AttributeSet attrs,        int defStyleAttr) {    super(context, attrs, defStyleAttr);    getAttrs(context, attrs);    init(context);}/** * 初始化布局 *  * @param context */private void init(Context context) {    this.context = context;    initDropDownStyle();    super.setOnScrollListener(this);}private void initDropDownStyle() {    if (headerLayout != null) {        if (isDropDrownStyle) {            addHeaderView(headerLayout);        } else {            removeHeaderView(headerLayout);        }        return;    }    if (!isDropDrownStyle) {        return;    }    headerReleaseMinDistance = getResources().getDimensionPixelSize(            R.dimen.drop_drown_list_header_release_min_distance);    flipAnimation = new RotateAnimation(0, 180,            RotateAnimation.RELATIVE_TO_SELF, 0.5f,            RotateAnimation.RELATIVE_TO_SELF, 0.5f);    flipAnimation.setInterpolator(new LinearInterpolator());    flipAnimation.setDuration(250);    flipAnimation.setFillAfter(true);    reverseFlipAnimation = new RotateAnimation(-180, 0,            RotateAnimation.RELATIVE_TO_SELF, 0.5f,            RotateAnimation.RELATIVE_TO_SELF, 0.5f);    reverseFlipAnimation.setInterpolator(new LinearInterpolator());    reverseFlipAnimation.setDuration(250);    reverseFlipAnimation.setFillAfter(true);    headerDefaultText = context            .getString(R.string.drop_drown_list_header_default_text);    headerPullText = context            .getString(R.string.drop_drown_list_header_pull_text);    headerReleaseText = context            .getString(R.string.drop_drown_list_header_release_text);    headerLoadingText = context            .getString(R.string.drop_drown_list_header_loading_text);    LayoutInflater inflater = (LayoutInflater) context            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);    headerLayout = (RelativeLayout) inflater.inflate(            R.layout.drop_drown_list_header, null);    headerText = (TextView) headerLayout            .findViewById(R.id.drop_drown_list_header_default_text);    headerImage = (ImageView) headerLayout            .findViewById(R.id.drop_drown_list_header_image);    headerProgressBar = (ProgressBar) headerLayout            .findViewById(R.id.drop_drown_list_header_progress_bar);    headerSecondText = (TextView) headerLayout            .findViewById(R.id.drop_down_list_header_second_text);    headerLayout.setClickable(true);    headerLayout.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View v) {            onDropDown();        }    });    headerText.setText(headerDefaultText);    addHeaderView(headerLayout);    measureHeaderLayout(headerLayout);    headerOriginalHeight = headerLayout.getMeasuredHeight();    headerOriginalTopPadding = headerLayout.getPaddingTop();    currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {    hasReachedTop = false;    switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN:        actionDownPointY = ev.getY();        break;    case MotionEvent.ACTION_MOVE:        adjustHeaderPadding(ev);        break;    case MotionEvent.ACTION_UP:        if (!isVerticalFadingEdgeEnabled()) {            setVerticalScrollBarEnabled(false);        }        if (getFirstVisiblePosition() == 0                && currentHeaderStatus != HEADER_STATUS_LOADING) {            switch (currentHeaderStatus) {            case HEADER_STATUS_RELEASE_TO_LOAD:                onDropDown();                break;            case HEADER_STATUS_DROP_DROWN_TO_LAOD:                setHeaderStatusClickToLoad();                setSecondPositionVisible();                break;            }        }        break;    }    return super.onTouchEvent(ev);}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {    currentScrollState = scrollState;    if (currentScrollState == SCROLL_STATE_IDLE) {        hasReachedTop = false;    }    if (onScrollListener != null) {        onScrollListener.onScrollStateChanged(view, scrollState);    }}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,        int visibleItemCount, int totalItemCount) {    if (currentScrollState == SCROLL_STATE_TOUCH_SCROLL            && currentHeaderStatus != HEADER_STATUS_LOADING) {        if (firstVisibleItem == 0) {            headerImage.setVisibility(View.VISIBLE);            int pointButtom = headerOriginalHeight                    + headerReleaseMinDistance;            if (headerLayout.getBottom() >= pointButtom) {                setHeaderStatusReleaseToLoad();            } else if (headerLayout.getBottom() < pointButtom) {                setHeaderStatusDropDownToLoad();            }        } else {            setHeaderStatusClickToLoad();        }    } else if (currentHeaderStatus == SCROLL_STATE_FLING            && firstVisibleItem == 0            && currentHeaderStatus != HEADER_STATUS_LOADING) {        setSecondPositionVisible();        hasReachedTop = true;    } else if (currentScrollState == SCROLL_STATE_FLING && hasReachedTop) {        setSecondPositionVisible();    }    if (onScrollListener != null) {        onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,                totalItemCount);    }}public void setSecondPositionVisible() {    if (getAdapter() != null && getAdapter().getCount() > 0            && getFirstVisiblePosition() == 0) {        setSelection(1);    }}private void adjustHeaderPadding(MotionEvent ev) {    int pointCount = ev.getHistorySize();    if (isVerticalFadingEdgeEnabled()) {        setVerticalScrollBarEnabled(false);    }    for (int i = 0; i < pointCount; i++) {        if (currentHeaderStatus == HEADER_STATUS_DROP_DROWN_TO_LAOD                || currentHeaderStatus == HEADER_STATUS_RELEASE_TO_LOAD) {            headerLayout                    .setPadding(                            headerLayout.getPaddingLeft(),                            (int) (((ev.getHistoricalY(i) - actionDownPointY) - headerOriginalHeight) / headerPaaddingTopRate),                            headerLayout.getPaddingRight(),                            headerLayout.getPaddingBottom());        }    }}private void onDropDown() {    if (currentHeaderStatus != HEADER_STATUS_LOADING            && onDropDownListener != null) {        onDropDownBegin();        onDropDownListener.onDropDown();    }}private void onDropDownBegin() {    setHeaderStatusLoading();}/** * headerLayout的初始状态 */private void setHeaderStatusClickToLoad() {    if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) {        resetHeaderPadding();        headerImage.clearAnimation();        headerImage.setVisibility(View.GONE);        headerProgressBar.setVisibility(View.GONE);        headerText.setText(headerDefaultText);        currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD;    }}/** * headerLayout的下拉状态 */private void setHeaderStatusDropDownToLoad() {    if (currentHeaderStatus != HEADER_STATUS_DROP_DROWN_TO_LAOD) {        headerImage.setVisibility(View.VISIBLE);        if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) {            headerImage.clearAnimation();            headerImage.startAnimation(reverseFlipAnimation);        }        headerProgressBar.setVisibility(View.GONE);        headerText.setText(headerPullText);        if (isVerticalFadingEdgeEnabled()) {            setVerticalScrollBarEnabled(false);        }        currentHeaderStatus = HEADER_STATUS_DROP_DROWN_TO_LAOD;    }}private void setHeaderStatusReleaseToLoad() {    if (currentHeaderStatus != HEADER_STATUS_RELEASE_TO_LOAD) {        headerImage.setVisibility(View.GONE);        headerImage.clearAnimation();        headerImage.startAnimation(flipAnimation);        headerProgressBar.setVisibility(View.GONE);        headerText.setText(headerReleaseText);        currentHeaderStatus = HEADER_STATUS_RELEASE_TO_LOAD;    }}private void setHeaderStatusLoading() {    if (currentHeaderStatus != HEADER_STATUS_LOADING) {        resetHeaderPadding();        headerImage.setVisibility(View.GONE);        headerImage.clearAnimation();        headerProgressBar.setVisibility(View.VISIBLE);        headerText.setText(headerLoadingText);        currentScrollState = HEADER_STATUS_LOADING;        setSelection(0);    }}private void resetHeaderPadding() {    headerLayout.setPadding(headerLayout.getPaddingLeft(),            headerOriginalTopPadding, headerLayout.getPaddingRight(),            headerLayout.getPaddingBottom());}private void measureHeaderLayout(View child) {    ViewGroup.LayoutParams p = child.getLayoutParams();    if (p == null) {        p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                ViewGroup.LayoutParams.WRAP_CONTENT);    }    int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);    int lpHeight = p.height;    int childHeightSpace;    if (lpHeight > 0) {        childHeightSpace = MeasureSpec.makeMeasureSpec(lpHeight,                MeasureSpec.EXACTLY);    } else {        childHeightSpace = MeasureSpec.makeMeasureSpec(0,                MeasureSpec.UNSPECIFIED);    }    child.measure(childWidthSpec, childHeightSpace);}private OnDropDownListener onDropDownListener;public void OnDropDownComplete(CharSequence secondText) {    setHeaderSecondText(secondText);    onDropDownComplete();}public void setHeaderSecondText(CharSequence secondText) {    if (secondText == null) {        headerSecondText.setVisibility(View.GONE);    } else {        headerSecondText.setVisibility(View.VISIBLE);        headerSecondText.setText(secondText);    }}public void onDropDownComplete() {    setHeaderStatusClickToLoad();    if (headerLayout.getBottom() > 0) {        invalidateViews();        setSecondPositionVisible();    }}public void setOnDropDownListener(OnDropDownListener listener) {    onDropDownListener = listener;}public interface OnDropDownListener {    public void onDropDown();}private void getAttrs(Context context, AttributeSet attrs) {    TypedArray ta = context.obtainStyledAttributes(attrs,            R.styleable.drop_down_list_attr);    isDropDrownStyle = ta.getBoolean(            R.styleable.drop_down_list_attr_isDropDownStyle, false);    ta.recycle();}/** * 使listView的第二个item可见 */@Overridepublic void setAdapter(ListAdapter adapter) {    // TODO Auto-generated method stub    super.setAdapter(adapter);    setSecondPositionVisible();}

}
下拉刷新中有四种状态分别为初始状态, 下拉状态, 释放刷新状态,刷新状态。在onTouchEvent()中通过getAction()方法获取到当前的按下的状态 在ACTION_DOWN状态获取点击时Y轴的坐标,在ACTION_MOVE 调节header布局的在Y轴的padding,在ACTION_UP状态下 若在释放刷新状态, 就会加载刷新,在下拉状态则返回初始状态。
在onScroll中根据滚动状态来判断刷新状态,当滚动的距离大于设定的距离是变为释放刷新状态,小于设定距离时变为下拉状态

源码如下http://download.csdn.net/detail/coder0408/8858767

0 0
原创粉丝点击