android 下拉刷新

jopen 11年前發布 | 25K 次閱讀 Android Android開發 移動開發

現在android應用里面下拉刷新比較多

public class MyListView extends ListView implements OnScrollListener {

private static final String TAG = "listview";

private final static int RELEASE_To_REFRESH = 0;
private final static int PULL_To_REFRESH = 1;
private final static int REFRESHING = 2;
private final static int DONE = 3;
private final static int LOADING = 4;

// 實際的padding的距離與界面上偏移距離的比例
private final static int RATIO = 3;

private LayoutInflater inflater;

private LinearLayout headView;

private TextView tipsTextview;
private TextView lastUpdatedTextView;
private ImageView arrowImageView;
private ProgressBar progressBar;


private RotateAnimation animation;
private RotateAnimation reverseAnimation;

// 用于保證startY的值在一個完整的touch事件中只被記錄一次
private boolean isRecored;

private int headContentWidth;
private int headContentHeight;

private int startY;
private int firstItemIndex;

private int state;

private boolean isBack;

private OnRefreshListener refreshListener;

private boolean isRefreshable;

public MyListView(Context context) {
    super(context);
    init(context);
}

public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

private void init(Context context) {
    setCacheColorHint(context.getResources().getColor(R.color.transparent));
    inflater = LayoutInflater.from(context);

    headView = (LinearLayout) inflater.inflate(R.layout.head, null);

    arrowImageView = (ImageView) headView
            .findViewById(R.id.head_arrowImageView);
    arrowImageView.setMinimumWidth(70);
    arrowImageView.setMinimumHeight(50);
    progressBar = (ProgressBar) headView
            .findViewById(R.id.head_progressBar);
    tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
    lastUpdatedTextView = (TextView) headView
            .findViewById(R.id.head_lastUpdatedTextView);

    measureView(headView);
    headContentHeight = headView.getMeasuredHeight();
    headContentWidth = headView.getMeasuredWidth();

    headView.setPadding(0, -1 * headContentHeight, 0, 0);
    headView.invalidate();

    Log.v("size", "width:" + headContentWidth + " height:"
            + headContentHeight);

    addHeaderView(headView, null, false);
    setOnScrollListener(this);

    animation = new RotateAnimation(0, -180,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    animation.setInterpolator(new LinearInterpolator());
    animation.setDuration(250);
    animation.setFillAfter(true);

    reverseAnimation = new RotateAnimation(-180, 0,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    reverseAnimation.setInterpolator(new LinearInterpolator());
    reverseAnimation.setDuration(200);
    reverseAnimation.setFillAfter(true);

    state = DONE;
    isRefreshable = false;
}

public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2,
        int arg3) {
    firstItemIndex = firstVisiableItem;
}

public void onScrollStateChanged(AbsListView arg0, int arg1) {
}

public boolean onTouchEvent(MotionEvent event) {

    if (isRefreshable) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (firstItemIndex == 0 && !isRecored) {
                isRecored = true;
                startY = (int) event.getY();
                Log.v(TAG, "在down時候記錄當前位置‘");
            }
            break;

        case MotionEvent.ACTION_UP:

            if (state != REFRESHING && state != LOADING) {
                if (state == DONE) {
                    // 什么都不做
                }
                if (state == PULL_To_REFRESH) {
                    state = DONE;
                    changeHeaderViewByState();

                    Log.v(TAG, "由下拉刷新狀態,到done狀態");
                }
                if (state == RELEASE_To_REFRESH) {
                    state = REFRESHING;
                    changeHeaderViewByState();
                    onRefresh();

                    Log.v(TAG, "由松開刷新狀態,到done狀態");
                }
            }

            isRecored = false;
            isBack = false;

            break;

        case MotionEvent.ACTION_MOVE:
            int tempY = (int) event.getY();

            if (!isRecored && firstItemIndex == 0) {
                Log.v(TAG, "在move時候記錄下位置");
                isRecored = true;
                startY = tempY;
            }

            if (state != REFRESHING && isRecored && state != LOADING) {

                // 保證在設置padding的過程中,當前的位置一直是在head,否則如果當列表超出屏幕的話,當在上推的時候,列表會同時進行滾動

                // 可以松手去刷新了
                if (state == RELEASE_To_REFRESH) {

                    setSelection(0);

                    // 往上推了,推到了屏幕足夠掩蓋head的程度,但是還沒有推到全部掩蓋的地步
                    if (((tempY - startY) / RATIO < headContentHeight)
                            && (tempY - startY) > 0) {
                        state = PULL_To_REFRESH;
                        changeHeaderViewByState();

                        Log.v(TAG, "由松開刷新狀態轉變到下拉刷新狀態");
                    }
                    // 一下子推到頂了
                    else if (tempY - startY <= 0) {
                        state = DONE;
                        changeHeaderViewByState();

                        Log.v(TAG, "由松開刷新狀態轉變到done狀態");
                    }
                    // 往下拉了,或者還沒有上推到屏幕頂部掩蓋head的地步
                    else {
                        // 不用進行特別的操作,只用更新paddingTop的值就行了
                    }
                }
                // 還沒有到達顯示松開刷新的時候,DONE或者是PULL_To_REFRESH狀態
                if (state == PULL_To_REFRESH) {

                    setSelection(0);

                    // 下拉到可以進入RELEASE_TO_REFRESH的狀態
                    if ((tempY - startY) / RATIO >= headContentHeight) {
                        state = RELEASE_To_REFRESH;
                        isBack = true;
                        changeHeaderViewByState();

                        Log.v(TAG, "由done或者下拉刷新狀態轉變到松開刷新");
                    }
                    // 上推到頂了
                    else if (tempY - startY <= 0) {
                        state = DONE;
                        changeHeaderViewByState();

                        Log.v(TAG, "由DOne或者下拉刷新狀態轉變到done狀態");
                    }
                }

                // done狀態下
                if (state == DONE) {
                    if (tempY - startY > 0) {
                        state = PULL_To_REFRESH;
                        changeHeaderViewByState();
                    }
                }

                // 更新headView的size
                if (state == PULL_To_REFRESH) {
                    headView.setPadding(0, -1 * headContentHeight
                            + (tempY - startY) / RATIO, 0, 0);

                }

                // 更新headView的paddingTop
                if (state == RELEASE_To_REFRESH) {
                    headView.setPadding(0, (tempY - startY) / RATIO
                            - headContentHeight, 0, 0);
                }

            }

            break;
        }
    }

    return super.onTouchEvent(event);
}

// 當狀態改變時候,調用該方法,以更新界面
private void changeHeaderViewByState() {
    switch (state) {
    case RELEASE_To_REFRESH:
        arrowImageView.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.GONE);
        tipsTextview.setVisibility(View.VISIBLE);
        lastUpdatedTextView.setVisibility(View.VISIBLE);

        arrowImageView.clearAnimation();
        arrowImageView.startAnimation(animation);

        tipsTextview.setText("松開刷新");

        Log.v(TAG, "當前狀態,松開刷新");
        break;
    case PULL_To_REFRESH:
        progressBar.setVisibility(View.GONE);
        tipsTextview.setVisibility(View.VISIBLE);
        lastUpdatedTextView.setVisibility(View.VISIBLE);
        arrowImageView.clearAnimation();
        arrowImageView.setVisibility(View.VISIBLE);
        // 是由RELEASE_To_REFRESH狀態轉變來的
        if (isBack) {
            isBack = false;
            arrowImageView.clearAnimation();
            arrowImageView.startAnimation(reverseAnimation);

            tipsTextview.setText("下拉刷新");
        } else {
            tipsTextview.setText("下拉刷新");
        }
        Log.v(TAG, "當前狀態,下拉刷新");
        break;

    case REFRESHING:

        headView.setPadding(0, 0, 0, 0);

        progressBar.setVisibility(View.VISIBLE);
        arrowImageView.clearAnimation();
        arrowImageView.setVisibility(View.GONE);
        tipsTextview.setText("正在刷新...");
        lastUpdatedTextView.setVisibility(View.VISIBLE);

        Log.v(TAG, "當前狀態,正在刷新...");
        break;
    case DONE:
        headView.setPadding(0, -1 * headContentHeight, 0, 0);

        progressBar.setVisibility(View.GONE);
        arrowImageView.clearAnimation();
        arrowImageView.setImageResource(R.drawable.arrow);
        tipsTextview.setText("下拉刷新");
        lastUpdatedTextView.setVisibility(View.VISIBLE);

        Log.v(TAG, "當前狀態,done");
        break;
    }
}

public void setonRefreshListener(OnRefreshListener refreshListener) {
    this.refreshListener = refreshListener;
    isRefreshable = true;
}

public interface OnRefreshListener {
    public void onRefresh();
}

public void onRefreshComplete() {
    state = DONE;
    lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());
    changeHeaderViewByState();
}

private void onRefresh() {
    if (refreshListener != null) {
        refreshListener.onRefresh();
    }
}

// 此方法直接照搬自網絡上的一個下拉刷新的demo,此處是“估計”headView的width以及height
private void measureView(View child) {
    ViewGroup.LayoutParams p = child.getLayoutParams();
    if (p == null) {
        p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
    }
    int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
    int lpHeight = p.height;
    int childHeightSpec;
    if (lpHeight > 0) {
        childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
                MeasureSpec.EXACTLY);
    } else {
        childHeightSpec = MeasureSpec.makeMeasureSpec(0,
                MeasureSpec.UNSPECIFIED);
    }
    child.measure(childWidthSpec, childHeightSpec);
}

public void setAdapter(BaseAdapter adapter) {
    lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());
    super.setAdapter(adapter);
}

}</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!