1. 程式人生 > >ListView實現上拉載入&下拉重新整理

ListView實現上拉載入&下拉重新整理

上拉載入&下拉重新整理

思路詳解:

自定義的帶有下拉重新整理和上拉載入的ListView開始時,跟系統的ListView一樣。不過多了個header和footer只不過這兩個佈局以不同的方式隱藏起來了而已。(header是在手機螢幕外的上面,footer是直接隱藏起來了。因為下拉和上拉載入不同,下拉載入有手勢判斷,要出現動畫效果,根據下拉的各種手勢,來設定具體的操作。如果直接跟footer一樣首先預設header的View.setVisibility(GONE),當有下拉手勢時再設定View.setVisibility(View.VISIBLE)就會沒有良好的動畫效果。)

如下圖所示:

上拉載入:

上拉載入適用於需要載入的資料量很大時,如果一下子載入完。會使ListView出現卡頓。這時候,如果利用上拉載入。先載入一部分資料。當上拉時,再載入其他的一部分資料。這樣就會有很好的使用者體驗。

接下來看上拉載入邏輯:上拉載入我們利用的是AbsListView.OnScrollListener這個介面。 它有兩個方法需要重寫:

1.publicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {};

//滾動時一直回撥,直到停止滾動時才停止回撥。單擊時回撥一次。

//firstVisibleItem:當前能看見的第一個列表項ID(從0開始)

//visibleItemCount:當前能看見的列表項個數(小半個也算)

//totalItemCount:列表項共數
2.publicvoid onScrollStateChanged(AbsListView view,int scrollState) {};

//正在滾動時回撥,回撥2-3次,手指沒拋則回撥2次。scrollState = 2的這次不回撥

//回撥順序如下

//第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滾動

//第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了拋的動作(手指離開螢幕前,用力滑了一下)

//第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滾動

//當螢幕停止滾動時為0;當螢幕滾動且使用者使用的觸碰或手指還在螢幕上時為1;

//由於使用者的操作,螢幕產生慣性滑動時為2

//當滾到最後一行且停止滾動時,執行載入

自定義LoadListView

1.定義變數

private int lastVisibleItem; //最後一個可見項

private int totalItems; //總的item

private View footer; //底部View+頭部View;

private boolean isLoading = false;//是否正在載入

private ILoadListener iListener;//自定義的一個載入介面。暴露給MainActivity讓它實現具體載入操作。可以根據需求不同而改寫。

2.載入佈局檔案及設定監聽

private void initViews(Context context) {

//獲得footer+header佈局檔案

LayoutInflater inflater =LayoutInflater.from(context);

footer = inflater.inflate(R.layout.footer,null);

footer.findViewById(R.id.ll_footer).setVisibility(GONE);//初始化時設定footer不可見

this.addFooterView(footer);

this.setOnScrollListener(this);//設定滾動監

}

3.重寫OnScrollListener的兩個方法

4.完成介面設定

/**

* 載入更多資料的回撥介面

*/

public interface ILoadListener {

    public void onLoad();

}

//上拉載入完畢

public void loadCompleted(){

    isLoading =false;
    
    footer.findViewById(R.id.ll_footer).setVisibility(GONE);

}


public void setInterface(ILoadListener iListener){

    this.iListener=iListener;

}

5.在MainActivity中實現LoadListView暴露的介面中的onLoad方法

//實現onLoad()方法。

@Override

public void onLoad() {

    //新增延時效果模擬資料載入

    Handler handler= new Handler() ;

    handler.postDelayed(new Runnable() {

        @Override

        public void run() {
    
        initNewDatas();//得到新資料

        arrayAdapter.notifyDataSetChanged();//重新整理ListView;

        mListView.loadCompleted();

        }

    }, 2000);

}

上拉載入資料完成。

下拉重新整理:

1.header佈局檔案

2.在LoadListView中定義變數

private boolean isRemark = false;//判斷是否在當前頁的最頂端並下滑

private int startY; //Y座標 記錄手指開始按下的座標

private RLoadListener rLoadListener;//自定義的一個載入介面。暴露給MainActivity讓它實現具體載入操作。可以根據需求不同而改寫。

private int scrollState;//當前滾動的 狀態

private int headerHeight;//頂部佈局檔案的高度

final int NONE= 0;//正常狀態

final int PULL =1;//下拉

final int RELESE =2;//釋放

final int REFLASHING =3; //重新整理

private int state=0;//判斷當前狀態,預設為正常狀態

private int firstVisibleItem;//第一個可見項

private View header; //頭部View;

3.新增頭部到ListView中

這裡新增頭佈局的時候需要計算header到底要移出螢幕多少的距離(移出的距離即為header的高),並且要告知父佈局

4.在OnScrollListener的兩個方法中記錄一些狀態量便於後面對OnTouch事件的操作

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

    this.scrollState =scrollState;

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int                 
            totalItemCount) {

    this.firstVisibleItem = firstVisibleItem;

}

5.利用OnTouchEvent對下拉手勢操作進行監聽:

先來說明下拉重新整理會出現的情況:

1.下拉距離過短,不進行資料重新整理。

2.下拉到一定距離重新整理資料。

當進行下拉重新整理的時候,手勢有3種狀態:

1.剛按下的時候;

2.手指下滑移動的時候;

3.手指擡起釋放的時候。

這3種手指狀態又對應了header不同的View狀態,然後根據view的狀態,再來改變header的顯示。

6.下拉重新整理介面,暴露給MainActivity來具體實現到底刷新出什麼資料:

/**

* 下拉重新整理介面

*/

public interface RLoadListener{

    public void onRefresh();

}

public void setReflashInterface(RLoadListener rLoadListener){

    this.rLoadListener =rLoadListener;

}

7.重新整理完要做的工作

/**

* 獲取完整資料

*

*/

public void reflashComplete(){

    state = NONE;

    isRemark = false;

    reflashViewByState();

    TextView lasetupdate_time = (TextView) header.findViewById(R.id.tv_lastupdate_time);

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");

    Date date = new Date(System.currentTimeMillis());

    String time = simpleDateFormat.format(date);

    lasetupdate_time.setText(time);


}

8.在MainActivity中應用LoadListView

SwipeRefreshLayout實現下拉重新整理(僅效果)

  • isRefreshing()

判斷當前的狀態是否是重新整理狀態。

  • setColorSchemeResources(int... colorResIds)

設定下拉進度條的顏色主題,引數為可變引數,並且是資源id,可以設定多種不同的顏色,每轉一圈就顯示一種顏色。

  • setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)

設定監聽,需要重寫onRefresh()方法,頂部下拉時會呼叫這個方法,在裡面實現請求資料的邏輯,設定下拉進度條消失等等。

  • setProgressBackgroundColorSchemeResource(int colorRes)

設定下拉進度條的背景顏色,預設白色。

  • setRefreshing(boolean refreshing)

設定重新整理狀態,true表示正在重新整理,false表示取消重新整理。

使用:

1.設定佈局

<android.support.v4.widget.SwipeRefreshLayout         
                 xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/swipe_refresh"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <ListView

        android:id="@+id/list_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent">
    </ListView>

</android.support.v4.widget.SwipeRefreshLayout>

2.在程式碼中使用

在該佈局檔案對應的Activity或其他類中獲取佈局id,先設定ListView顯示的介面卡,然後再設定SwipeRefreshLayout。

注:不能在onCreate中設定,這個表示當前是重新整理狀態,如果一進來就是重新整理狀態,SwipeRefreshLayout會遮蔽掉下拉事件          //swipeRefreshLayout.setRefreshing(true);

//宣告控制元件

private SwipeRefreshLayout swiper;

private ListView mListView;

//宣告並初始化ListView的資料來源

private List<String> list = new ArrayList<>();

//宣告ListView的介面卡

private ArrayAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.swipe_layout);

    //初始化SwipeRefreshLayout

    swiper = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);

    //為SwipeRefreshLayout設定監聽事件

    swiper.setOnRefreshListener(this);
    
    //為SwipeRefreshLayout設定重新整理時的顏色變化,最多可以設定4種

    swiper.setColorSchemeResources(android.R.color.holo_blue_bright,

    android.R.color.holo_green_light,

    android.R.color.holo_orange_light,

    android.R.color.holo_red_light);

    //初始化ListView

    mListView = (ListView) findViewById(R.id.list_view);

    //初始化介面卡

    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData());
    
    //設定介面卡

    mListView.setAdapter(adapter);

}

//增加資料

private List<String> getData() {

    list.add("hello");

    list.add("this is johnsonHou");

    list.add("an android rookie developer");

    list.add("love android");

    return list;

}

//實現OnRefreshListener 的onRefresh()方法

@Override

public void onRefresh() {

    //重新整理

    new Handler().postDelayed(new Runnable() {

        @Override

        public void run() {

        //結束後停止重新整理

        swiper.setRefreshing(false);
    
        }

    }, 3000);

}

//簡單示例,手動新增資料

private void refreshData() {

    list.add(0, String.valueOf((int) (Math.random() * 10)));

    adapter.notifyDataSetChanged();

}