歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

帶下拉刷新操作的ListView

我們在做一些Listview的時候為了便於用戶操作通常需要這種功能,向下拉動Listview列表時候可以進行對列表的更新操作。

我們知道系統自帶的列表功能是非常少的,而為了讓我們工程的列表能有我們想要的功能,我們自然而然想對Listview進行自定義

MyListView類:

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); 
    } 
 

Copyright © Linux教程網 All Rights Reserved