listview實現上拉加載


Android實現listview的上拉加載更多
當前實例爲最基本的上拉加載實現,  學習者可根據邏輯自創建...

實現邏輯:

1、創建自定義ListView,並且監聽其滾動的事件
2、自定義ListView的類中應實現一個內部接口,用來實現加載更多數據的邏輯
3、使用該listview,且在引用類中實現加載更多數據的內部接口
4、(最好自定義Adapter)

最終效果



下圖爲最基本的項目結構:

下爲每一個步驟的詳解:

1、創建自定義ListView,並且監聽其滾動的事件


繼承ListView:下拉的時候需要動態的加載一個佈局文件提示給用戶,告知我們現在正在幫您刷新數據 。
實現OnScrollListener: 只有在第一個item爲最頂部的時候纔開始進行我們的‘下拉加載’更多的代碼邏輯,需要程序員知道我們現在能否進行觸發該邏輯代碼

1.1 類屬性的聲明
    private int firstVisibleItem;       // 表示當前listview是否在第一行
    private View v;                     // 提示的加載佈局
    private IReflashListener iReflashListener;  // 實現刷新的內部接口
1.2 類初始化
public MyListView(Context context) {
        super(context, null);
        init();
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {
        setOnScrollListener(this);
    }
1.3 對其OnScrollListener的方法實現
@Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        /**
         * firstVisibleItem==0: 表示在第一個Item項
         * scrollState!=0: 該listview正在移動
         */
        if (firstVisibleItem == 0 && scrollState != 0) {
            // 進行添加頂部佈局
            v = LayoutInflater.from(getContext()).inflate(R.layout.item_top_layout, null);
            this.addHeaderView(v);

            if (iReflashListener != null)
                iReflashListener.onReflash();        // 加載數據

        } else {
            if (v != null) {
                // 隱藏頂部佈局
                this.removeHeaderView(v);
            }

        }

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        this.firstVisibleItem = firstVisibleItem;
    }
動態加載數據的操作放在onScrollStateChanged中的原因:只有用戶在滾動該listview的時候才能進行加載數據。
onScroll方法中的firstVisibleItem:  當前listview的操作緩存中的第一條item是該數據源的第幾條。

2、自定義ListView的類中應實現一個內部接口,用來實現加載更多數據的邏輯

以上的內容基本上已經實現了該上拉刷新的功能。

3、動態佈局的創建

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/seekBar"
        style="@android:style/Widget.ProgressBar.Small" />


    <TextView android:text="下拉加載"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
將該組件放在任意的layout中即可。

4、使用該listview,且在引用類中實現加載更多數據的內部接口

稍微值得注意的是,在我們listview的引用文件中,該組件需要使用以下方式
<com.example.administrator.listviewautoload.MyListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
此方式爲使用自定義組件。

5、adapter實現

在該listview中,建議使用自定義adapter。(或者可以說任何listview都建議使用自定義adapter)
adapter大家都用過不少了,就直接將adapter源碼貼出

package com.example.administrator.listviewautoload;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * 進行數據與listview的綁定
 */
public class MyAdapter extends BaseAdapter {

    private List<String> lists; // item總數據
    private Context context;    // 上下文(此處級別因爲activity)
    private ViewHolder viewHolder;
    private boolean flag; // 是否可以加載更多


    public MyAdapter(List<String> lists, Context context) {
        this.lists = lists;
        this.context = context;
    }


    @Override
    public int getCount() {
        return lists.size();
    }

    @Override
    public Object getItem(int position) {
        return lists.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        /**
         * 做出一定的listview優化
         */
        if (convertView == null) {

            convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.textView.setText(lists.get(position));

        return convertView;
    }


    class ViewHolder {

        TextView textView;

    }


}


這個adapter還是非常簡單的,內部定義了一個ViewHolder類。 包含了一個listview item的組件。使用此種getView方法方式可以最優化的幫組我們節省Android內存(建議使用)。



最後一步,那就是動態的添加數據


現爲listview綁定一個數據適配器


在該類中,我們需要實現該listview的動態加載數據接口
public class MainActivity extends Activity implements MyListView.IReflashListener

我們實現它的方法,在該方法中就可以調用自己特有的加載數據方法,只要放入到adapter的數據源中,調用adapte的notifyDataSetChanged即可
(notifyDataSetChanged: 通知進行適配的Adapter, 表示這個數據源的數據已經更新了,你現在要在主界面中同時做出刷新 )

 @Override
    public void onReflash() {
        Toast.makeText(this, "MainActivity   onReflash", Toast.LENGTH_SHORT).show();
        /**
         * 開始加載刷新的數據(此爲模擬動態加載出來的數據)
         */
        for (int i = 0; i < 2; i++) {
            lists.add(Integer.valueOf(lists.get(lists.size() - 1)) + 1 + "");
        }

        adapter.notifyDataSetChanged();

    }

至此,我們的功能就基本實現了,有木有特別簡單。 因仔細注意MainActivity的init方法中listview.setiReflashListener(this) ;
這句代碼一定要有, 否則在listview中就不能實現動態加載了。



這是筆者的第一篇博客,可能講的不是很詳細,但代碼幾乎全部都貼出來了。 學習者們應該很容易理解。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章