Android下拉重新整理上拉載入更多的擴充ListView

來源:互聯網
上載者:User

Android下拉重新整理上拉載入更多的擴充ListView
下拉重新整理上拉載入更多的擴充ListView

在很多APP我們都能看到,在一個列表上面,將手指往螢幕下面滑動,列表上方就會出現一個隱藏的View,一般寫有“下拉重新整理”等字樣,意味著,我們將手指往下面滑動,字樣又會變成 “放開重新整理” 字樣,這時候我們將手指放開螢幕,我們就會看到 字樣變為 “正在重新整理..." 並且旁邊還有一個旋轉的進度在旋轉等待,過了1、2秒後,列表的新的資料載入完成,這個提示的view就又隱藏起來了。這就是Android中下拉重新整理的控制項,現在我們就自己來實現一個這樣的控制項,首先我們來講解一下原理。如:

1、listView通過addHeaderView(header)一個方法可以添加頭布局View即 header,這個header就是顯示下拉重新整理的view,然後將header的topMargin設定為它高度header.getHeight()的負值,那麼它就被隱藏在了手機螢幕的頂部,如中所示;

2、將listview設定滑動監聽setOnscrollListner,用來監聽使用者手指的滑動狀態,可以判斷使用者手指的按下,滑動,抬起等一整套完整的手指滑動事件,然後根據手指向下滑動的距離,動態更新到listview的header的margin中,這樣整個listview就會往下滑動,此時隱藏在手機螢幕頂部的header也就會從螢幕頂部慢慢的滾動出來,如所示。當header完全滾動出來後,這個時候listView向下滑動的距離Height大於了header的高度,這個時候就跟新header的顯示狀態,header就顯示為 "放開重新整理",即放開手指listview就進行重新整理操作。

3、當header顯示為釋放重新整理的時候,這個時候手指離開螢幕,即點擊事件為MotionEvent.UP,這個時候螢幕就會顯示 ”正在重新整理...“ 並且左邊會有重新整理的進度條在進行重新整理等待,等到主Acitivity的新資料載入完成後就會隱藏掉header,這樣一個完正的下拉重新整理原理就講完了。

 

 

我們講完了下拉重新整理,截下拉我們講講上拉載入更多。

在很多listview列表資料中,當我們拉到底部時,就會出現一個 圓形進度條和一個”正在載入更多...“,主要是用於分頁載入網路資料,在我們訪問網路資料時,如果資料較多,基本都會使用分頁處理資料,讓資料一批一批的載入進來,這樣就會緩解手機端訪問大量資料的壓力,畢竟資料多,載入時間就會長,使用者的等待時間也會增加,不利於使用者體驗。所以上拉載入更多,就在listview中使用了起來,也是android開發必備的知識。

 

如所示,listview通過addFooterView(View view)就可以通過判斷是不是滑動到了底部,然後給listview添加底部view。讓後讓activity實現listview的重新整理介面,當listview滑動到了底部,然後響應介面,當載入更多的實現完成之後,就開始設定listiview的loadingComplete()方法,就將載入更多的view給隱藏掉。

 

好了原理就是那樣,現在我們看看效果

 

 

下面是 RefreshListView的代碼

 

package com.example.myfirst.pulltorefreshlist;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ImageView;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;import java.text.SimpleDateFormat;public class RefreshListView extends ListView implements OnScrollListener {    /**     * 下拉重新整理部分     */    private static final String TAG = "RefreshListView";    private int firstVisibleItemPosition;//listview中第一個可見item所在的位置position    private int downY;//手指在Y軸下拉滑動的距離    private int headerViewHeight;//下拉重新整理view的高度    private View headerView; //下拉重新整理的view    private final int DOWN_PULL_REFERESH = 0;//“下拉重新整理”狀態    private final int RELEASE_REFRESH = 1;//“放開重新整理”狀態    private final int REFRESHING = 2;//“正在重新整理”狀態    private int currentState = DOWN_PULL_REFERESH;//listView當前的狀態,預設為”下拉重新整理“狀態    private Animation upAnimation; //下拉式箭頭變為向上箭頭的動畫    private Animation downAnimation; //上拉箭頭變為向下箭頭的動畫    private ImageView ivArrow; //下拉式箭頭    private ProgressBar mProgressBar; //進度條    private TextView tvState; //顯示狀態的文本    private TextView tvLastUpdateTimes; //顯示最後更新的時間    /**     * 底部載入更多部分     */    private boolean isScrollToBottom;//判斷是不是滑到了底部    private View footerView; //底部的footer   view    private int footerViewHeight; //底部view的高度    private boolean isLoadingMore = false; //判斷是不是"載入更多"    /**     * listview的介面,監聽listview的下來重新整理和上拉載入更多     */    private OnRefreshListener mOnRefreshListener;    public RefreshListView(Context context, AttributeSet attrs) {        super(context, attrs);        initHeaderView();        initFooterView();        this.setOnScrollListener(this);    }    /**     * 初始化底部view     */    private void initFooterView() {        footerView = View.inflate(getContext(), R.layout.footer_layout, null);        //設定(0,0)以便系統測量footerView的寬高        footerView.measure(0, 0);        footerViewHeight = footerView.getMeasuredHeight();        footerView.setPadding(0, -footerViewHeight, 0, 0);        this.addFooterView(footerView);    }    /**     * 初始化頂部view     */    private void initHeaderView() {        headerView = View.inflate(getContext(), R.layout.header_layout, null);        ivArrow = (ImageView) headerView.findViewById(R.id.pull_to_refresh_icon);        mProgressBar = (ProgressBar) headerView.findViewById(R.id.refresh_progressbar);        tvState = (TextView) headerView.findViewById(R.id.hint_text);        tvLastUpdateTimes = (TextView) headerView.findViewById(R.id.refresh_time);        //最新動向        tvLastUpdateTimes.setText("最新動向:" + getLastUpdateTime());        //設定(0,0)以便系統測量footerView的寬高        headerView.measure(0, 0);        headerViewHeight = headerView.getMeasuredHeight();        headerView.setPadding(0, -headerViewHeight, 0, 0);        this.addHeaderView(headerView);        initAnimation();    }    /**     * 擷取最新動向時間     */    private String getLastUpdateTime() {        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");        return sdf.format(System.currentTimeMillis());    }    /**     * 初始化動畫     */    private void initAnimation() {        upAnimation = new RotateAnimation(0f, -180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);        upAnimation.setDuration(500);        upAnimation.setFillAfter(true);//設為true,表示動畫完成後,保持動畫後的狀態        downAnimation = new RotateAnimation(-180f, -360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);        downAnimation.setDuration(500);        downAnimation.setFillAfter(true);//設為true,表示動畫完成後,保持動畫後的狀態    }    /**     * listView的touche事件,通過判斷手指在listview上面的,按下、滑動、抬起等一套手指動作,來實現     * 下拉重新整理和上拉載入更多     *     * @param ev     * @return     */    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                downY = (int) ev.getY();                break;            case MotionEvent.ACTION_MOVE:                int moveY = (int) ev.getY();                //擷取滑動距離一半長度,以便手指在螢幕上面滑動了很長一段距離,headerview也不是很高,                //主要為了美觀,你可以不用除2,看你自己的設計,不過除2顯示效果要好點                int diff = (moveY - downY) / 2;                //設定頂部view距離頂部的padding距離                int paddingTop = -headerViewHeight + diff;                //如果當前可見的第一個position為0,                if (firstVisibleItemPosition == 0 && -headerViewHeight < paddingTop) {                    //paddingTop>0說明headerView完全拉出了頂部,並且目前狀態為”下拉重新整理“                    //則把目前狀態改為”放開重新整理“,並且調用refeshHeaderView()更新介面                    if (paddingTop > 10 && currentState == DOWN_PULL_REFERESH) {                        currentState = RELEASE_REFRESH;                        refreshHeaderView();                    } //paddingTop<0說明headerView沒有完全拉出了頂部,並且目前狀態為”放開重新整理“                    //則把目前狀態改為”下拉重新整理“,並且調用refeshHeaderView()更新介面;                    //這種情況就是,當完全拉出來之後,手指沒有抬起,然後往又回到頂部                    else if (paddingTop < 10 && currentState == RELEASE_REFRESH) {                        currentState = DOWN_PULL_REFERESH;                        refreshHeaderView();                    }                    //動態重新整理headerView的頂部padding,這樣lisview就在動態變化                    headerView.setPadding(0, paddingTop, 0, 0);                    return true;                }                break;            //手指抬起時,判斷listview當前的狀態            case MotionEvent.ACTION_UP:                //判斷當前的狀態                if (currentState == RELEASE_REFRESH) {                    //如果是”放開重新整理“,讓headerView的padding都為0                    headerView.setPadding(0, 0, 0, 0);                    // 把當前的狀態設為”正在重新整理“                    currentState = REFRESHING;                    refreshHeaderView();                    //判斷外面外面有沒有設定重新整理的介面                    if (mOnRefreshListener != null) {                        //如果設定了介面,就調用介面中的下拉重新整理的方法                        mOnRefreshListener.onDownPullRefresh();                    }                } else if (currentState == DOWN_PULL_REFERESH) {                    //如果目前狀態是”下拉重新整理“狀態,則將headerView隱藏掉                    headerView.setPadding(0, -headerViewHeight, 0, 0);                }                break;            default:                break;        }        return super.onTouchEvent(ev);    }    /**     * 根據目前狀態currentState來更新下拉重新整理view介面的控制項顯示內容?     */    private void refreshHeaderView() {        switch (currentState) {            case DOWN_PULL_REFERESH:                tvState.setText("下拉重新整理");                ivArrow.startAnimation(downAnimation);                break;            case RELEASE_REFRESH:                tvState.setText("放開重新整理");                ivArrow.startAnimation(upAnimation);                break;            case REFRESHING:                ivArrow.clearAnimation();                ivArrow.setVisibility(View.GONE);                mProgressBar.setVisibility(View.VISIBLE);                tvState.setText("正在重新整理...");                break;            default:                break;        }    }    /**     * 監聽listview滾動的狀態變化,如果滑到了底部,就“載入更多..."     */    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING) {            if (isScrollToBottom && !isLoadingMore) {                isLoadingMore = true;                footerView.setPadding(0, 0, 0, 0);                this.setSelection(this.getCount());                if (mOnRefreshListener != null) {                    mOnRefreshListener.onLoadingMore();                }            }        }    }    /**     * 監聽listview滾動的狀態變化,判斷當前是不是滑到了底部     *     * @param view     * @param firstVisibleItem     * @param visibleItemCount     * @param totalItemCount     */    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {        firstVisibleItemPosition = firstVisibleItem;        if (getLastVisiblePosition() == (totalItemCount - 1)) {            isScrollToBottom = true;        } else {            isScrollToBottom = false;        }    }    /**     * 設定監聽介面,當為     *     * @param listener     */    public void setOnRefreshListener(OnRefreshListener listener) {        mOnRefreshListener = listener;    }    /**     * 為外界提供的方法,當Activity中的資料載入完後,就調用這個方法來隱藏頂部的headerView     */    public void onRefreshComplete() {        headerView.setPadding(0, -headerViewHeight, 0, 0);        ivArrow.setVisibility(View.VISIBLE);        mProgressBar.setVisibility(View.GONE);        tvState.setText("下拉重新整理");        tvLastUpdateTimes.setText("最新動向時間:" + getLastUpdateTime());        currentState = DOWN_PULL_REFERESH;    }    /**     * 為外界提供的方法,當Activity中的載入更多資料載入完後,就調用這個方法來隱藏底部的footerView     */    public void loadMoreComplete() {        headerView.setPadding(0, -headerViewHeight, 0, 0);        isLoadingMore = false;    }    /**     * 設定介面,供外界實現,監聽listview的重新整理和載入更多的狀態     */    public interface OnRefreshListener {        /**         * 下拉重新整理         */        void onDownPullRefresh();        /**         * 上拉載入更多         */        void onLoadingMore();    }}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.