天天看點

Android Composite(ListView)詳解

目錄:

    1.ListView概述

    2.ListView使用中的重要角色(Adapter,ViewHolder,資料集,布局)

    3.ListView常用屬性

    4.ListView+ArrayAdapter

    5.ListView+SimpleCursorAdapter

    6.ListView+SimpleAdapter

    7.ListView+自定義Adapter(繼承BaseAdapter)

    8.下拉重新整理,上拉加載(SwipeRefreshLayout(google官方下來重新整理元件)+自定義上拉加載更多)

1.ListView概述

    見名知意,ListView即為顯示list集合的一個view控件,當然他不可能直接與資料适配顯示,她們之間需要adapter這個橋梁來适配

2.ListView使用中的重要角色(Adapter,ViewHolder,資料集,布局)

        Adapter:即為資料與布局提供橋梁進行适配,常見的Adapter有:ArrayAdapter,SimpleCursorAdapter,SimpleAdapter

            抽象的BaseAdapter。

        ViewHolder:ViewHolder模式其實非常優秀,他在其中扮演着優化ListView加載的效率角色(怎樣優化,代碼見,說起來總沒那麼容易了解)

        資料集:資料當然就不用說,就是需要顯示在使用者界面的一個集合,可以是圖檔+文字或者隻有文字。

        布局:就是整個ListView控件和單條資料的顯示樣式布局,換句話說就是定義你的單個資料應該如何顯示。

3.ListView常用屬性

android:choiceMode="multipleChoice|none|multipleChoiceModal|singleChoice":設定清單項選擇模式,單選,多選或者預設的無法選擇
    android:fastScrollEnabled="true":設定是否開啟快速滾動條
    android:fastScrollAlwaysVisible="true":設定是否總是顯示快速滾動條
    android:scrollbars="horizontal|vertical|none":設定滾動條,豎直,水準,無
    android:stackFromBottom="true|false":設定是否從底部開始顯示
    android:transcriptMode="alwaysScroll|normal|disabled":設定ListView在增加新項時是否自動滑動到底部
    android:divider="":設定item之間的分割(圖檔,顔色,@null都可以)
    android:fadingEdgeLength="":設定item陰影
    android:listSelector="":設定清單選中項的背景圖檔
    android:drawSelectorOnTop="true|false":設定選中項的背景是否顯示在選擇内容之上
           

4.ListView+ArrayAdapter

    4.1)主java類MainActivity.java

package com.example.listview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private ArrayList<String> list;
    private ArrayAdapter<String> arrayAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化布局
        listView = (ListView) findViewById(R.id.first_lv);
        //設定不滑動時是否顯示滑動條,true表示當滑動時顯示,不滑動時不顯示,false一直顯示
        //listView.setScrollbarFadingEnabled(false);
        //設定垂直ScrollBar是否開啟,不開啟在滑動的時候不顯示ScrollBar
        listView.setVerticalScrollBarEnabled(false);
        //初始化資料
        list = new ArrayList<String>();
        for (int i= 1;i<20;i++){
            list.add("資料"+i);
        }
        //初始化擴充卡
        //Context:表示目前context及MainActivity.this
        // int resource:單條資料顯示布局
        // List<T> objects:ArrayList資料集合
        arrayAdapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,list);
        //設定擴充卡
        listView.setAdapter(arrayAdapter);
    }

} 
           

    4.2)主布局檔案activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.listview.MainActivity">
    <!--
    android:choiceMode="multipleChoice|none|multipleChoiceModal|singleChoice":設定清單項選擇模式,單選,多選或者預設的無法選擇
    android:fastScrollEnabled="true":設定是否開啟快速滾動條
    android:fastScrollAlwaysVisible="true":設定是否總是顯示快速滾動條
    android:scrollbars="horizontal|vertical|none":設定滾動條,豎直,水準,無
    android:stackFromBottom="true|false":設定是否從底部開始顯示
    android:transcriptMode="alwaysScroll|normal|disabled":設定ListView在增加新項時是否自動滑動到底部
    android:divider="":設定item之間的分割(圖檔,顔色,@null都可以)
    android:fadingEdgeLength="":設定item陰影
    android:listSelector="":設定清單選中項的背景圖檔
    android:drawSelectorOnTop="true|false":設定選中項的背景是否顯示在選擇内容之上
    -->
<ListView
    android:id="@+id/first_lv"
    android:transcriptMode="disabled"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

</ListView>
</RelativeLayout>
           

    4.3)效果截圖

Android Composite(ListView)詳解

5.ListView+SimpleCursorAdapter(讀取顯示聯系人)

    ps:我們暫不深究如何對手機聯系人進行增删改查操作,隻是簡單使用它來實作ListView+SimpleCursorAdapter的使用

    5.1)主java類SimpleCursorAdapterActivity.java

package com.example.listview;

import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ListView;

/**
 * Created by elimy on 2016-08-25.
 */
public class SimpleCursorAdapterActivity extends AppCompatActivity {
    private ListView simpleCursorListView;
    private SimpleCursorAdapter simpleCursorAdapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.simple_cursor_activity);
        //初始化ListView控件
        simpleCursorListView = (ListView) findViewById(R.id.simple_cursor_lv);
        //執行個體化内容接收者
        ContentResolver resolver = getContentResolver();
        //此處通路查詢聯系人的方法和ContactsContract.Contacts.CONTENT_URI效果相同
/*        Uri uri=Uri.parse("content://com.android.contacts/contacts");
        Cursor cursor =resolver.query(uri,null,null,null,null);*/
        //通過内容接收者去查詢資料,傳回Cursor資料集
        //注意:People.CONTENT_URI被ContactsContract.Contacts.CONTENT_URI替代
        Cursor cursor =resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

        if(cursor==null){
            Log.d("cursor","cursor is null");
        }
        //執行個體化simpleCursorAdapter
       /* Context:表示目前的Context即SimpleCursorAdapterActivity.this,
        layout:單條資料的布局檔案ID,
        Cursor:資料庫查詢傳回的資料集,
        from:資料集需要顯示的的字段,
        to:布局檔案中與顯示字段對應的資源ID,
        flags:定義該adapter的行為
        */
        simpleCursorAdapter = new SimpleCursorAdapter(this,R.layout.simple_cursor_item,
               cursor,new String[]{ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts.NAME_RAW_CONTACT_ID},new int[]{R.id.call_name,R.id.call_number},0);
        //設定擴充卡到ListView
        simpleCursorListView.setAdapter(simpleCursorAdapter);
/*        while (cursor.moveToNext()){
            String name =cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            Log.d("contact name:",name);
        }*/
    }
}   
           

    5.2)主布局xml檔案simple_cursor_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<ListView
    android:id="@+id/simple_cursor_lv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

</ListView>
</RelativeLayout>    
           

    5.3)單個item xml檔案simple_cursor_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_marginBottom="10dp"
    android:layout_marginTop="10dp"
    android:layout_height="match_parent">
<TextView
    android:id="@+id/call_name"
    android:textSize="24sp"
    android:text="name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
    <TextView
        android:gravity="center"
        android:textSize="18sp"
        android:layout_marginLeft="10dp"
        android:id="@+id/call_number"
        android:text="number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout> 
           

    注意:通路聯系人需要注冊權限:<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>

    5.4)效果截圖

Android Composite(ListView)詳解

6.ListView+SimpleAdapter

        6.1)主java類SimpleAdapterDemo.java

package com.example.listview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by elimy on 2016-08-28.
 */
public class SimpleAdapterDemo extends AppCompatActivity {
    private ArrayList<Map<String,Object>> myList;
    private HashMap<String,Object> myMap;
    private ListView simpleAdapterListView;
    private SimpleAdapter simpleAdapter;
    private ImageView icon;
    private TextView name_tv,desc_tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.simple_adpter);
       //初始化ListView
        simpleAdapterListView = (ListView) findViewById(R.id.simple_adapter_lv);
        //初始化simpleAdapter
        simpleAdapter = new SimpleAdapter(this,getMyList(),
        R.layout.simple_adapter_item,new String[]{"icon","name","desc"},
                new int[]{R.id.icon,R.id.name,R.id.desc});
        //設定擴充卡
        simpleAdapterListView.setAdapter(simpleAdapter);


    }
    /*
    * 封裝方法初始化資料
    * */
    public ArrayList<Map<String,Object>> getMyList(){
        //執行個體化帶泛型ArrayList
        myList =new ArrayList<Map<String, Object>>();
        //初始化HashMap
        myMap = new HashMap<String,Object>();
        //放入資料,這裡就直接put,如果有資料庫讀取資料可以将cursor類型資料轉換成map類型
        myMap.put("icon",R.drawable.a2);
        myMap.put("name","支付寶");
        myMap.put("desc","支付寶支付為大家!");
        myList.add(myMap);
        //第二條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a3);
        myMap.put("name","google浏覽器");
        myMap.put("desc","想看啥看啥!");
        myList.add(myMap);
        //第三條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a7);
        myMap.put("name","米聊");
        myMap.put("desc","和女神面對面!");
        myList.add(myMap);
        //第四條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a8);
        myMap.put("name","指南針");
        myMap.put("desc","想去哪兒,就去哪兒!");
        myList.add(myMap);
        //第五條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a9);
        myMap.put("name","時鐘");
        myMap.put("desc","時時刻刻,每分每秒都為你計算!");
        myList.add(myMap);
        return myList;
    }
}
           

        6.2)主布局simple_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/simple_adapter_lv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

    </ListView>
</RelativeLayout>
           

        6.3)單個item xml布局simple_adapter_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="85dp"
        android:layout_height="85dp"
        android:src="@drawable/a2"
        android:id="@+id/icon" />
    <RelativeLayout
        android:layout_alignBaseline="@+id/icon"
        android:layout_toRightOf="@+id/icon"
        android:id="@+id/tv_rLayout"
        android:orientation="vertical"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/name" />

        <TextView
            android:layout_marginTop="10dp"
            android:layout_below="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"
            android:id="@+id/desc"
            android:singleLine="true"
            android:ellipsize="end"
            />

    </RelativeLayout>

</RelativeLayout>
           

        6.4)效果截圖

Android Composite(ListView)詳解

7.ListView+自定義Adapter(繼承BaseAdapter)

    ps:有時候我們不僅僅是顯示資料,可能會在單個item中添加一些控件并實作控件的相關操作,比如添加:button,checkbox等

    7.1)自定義Adapter類CustomAdapter.java

package com.example.listview;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Map;

/**
 * Created by elimy on 2016-08-28.
 */
public class CustomAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<Map<String,Object>> list;
    private LayoutInflater inflater;
    /*
    * 帶參數構造方法
    * Context:指執行個體化CustomAdapter的上下文
    * ArrayList:表示需要适配的資料源
    * */
    public CustomAdapter(Context context, ArrayList<Map<String, Object>> list) {
        //記得初始化布局加載器
        this.inflater =LayoutInflater.from(context);
        this.context =context;
        this.list = list;
    }

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

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        if (holder==null){
           holder=new ViewHolder();
            if(convertView == null){
                //适配并綁定單個item的顯示布局
                convertView = inflater.inflate(R.layout.custom_adapter_item,null);

            }
            //如果ViewHolder映射關系不存在,則構造映射關系,如果存在直接複用
            holder.icon = (ImageView) convertView.findViewById(R.id.custom_icon);
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.desc = (TextView) convertView.findViewById(R.id.desc);
            holder.download = (Button) convertView.findViewById(R.id.download);
            convertView.setTag(holder);

        }else {
            //取出ViewHolder複用
            holder = (ViewHolder) convertView.getTag();
        }
        //從list中設定圖示到布局顯示
        holder.icon.setBackgroundResource((Integer) list.get(position).get("icon"));
        Integer res =(Integer) list.get(position).get("icon");
        Log.d("icon",res.toString());
        //設定name到布局顯示
        holder.name.setText((String) list.get(position).get("name"));
        //設定描述到布局顯示
        holder.desc.setText((String) list.get(position).get("desc"));
        //設定button監聽
        holder.download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ViewHolder holder = new ViewHolder();
                Log.d("click_debug",list.get(position).get("name")+"開始下載下傳");
                Toast.makeText(context,list.get(position).get("name")+"開始下載下傳",Toast.LENGTH_SHORT).show();
            }
        });
        return convertView;
    }

    /**
    *儲存布局控件,友善後面複用以此提高加載效率
    * */
    class ViewHolder{
        private ImageView icon;
        private TextView name,desc;
        private Button download;
    }
}
           

    7.2)主布局java類BaseAdapterActivity.java

package com.example.listview;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by elimy on 2016-08-28.
 */
public class BaseAdapterActivity extends AppCompatActivity {
    private ListView customAdapterListView;
    private CustomAdapter customAdapter;
    private ArrayList<Map<String,Object>> myList;
    private Map<String,Object> myMap;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_adapter);
        //初始化ListView控件
        customAdapterListView = (ListView) findViewById(R.id.custom_adapter_lv);
        //擷取資料
        ArrayList<Map<String,Object>> list =getMyList();
        //執行個體化自定義擴充卡
        customAdapter = new CustomAdapter(BaseAdapterActivity.this,list);
        //設定擴充卡
        customAdapterListView.setAdapter(customAdapter);
    }
    /*
    * 封裝方法初始化資料
    * */
    public ArrayList<Map<String,Object>> getMyList(){
        //執行個體化帶泛型ArrayList
        myList =new ArrayList<Map<String, Object>>();
        //初始化HashMap
        myMap = new HashMap<String,Object>();
        //放入資料,這裡就直接put,如果有資料庫讀取資料可以将cursor類型資料轉換成map類型
        myMap.put("icon",R.drawable.a2);
        myMap.put("name","支付寶");
        myMap.put("desc","支付寶支付為大家!");
        myList.add(myMap);
        //第二條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a3);
        myMap.put("name","google浏覽器");
        myMap.put("desc","想看啥看啥!");
        myList.add(myMap);
        //第三條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a7);
        myMap.put("name","米聊");
        myMap.put("desc","和女神面對面!");
        myList.add(myMap);
        //第四條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a8);
        myMap.put("name","指南針");
        myMap.put("desc","想去哪兒,就去哪兒!");
        myList.add(myMap);
        //第五條資料
        myMap = new HashMap<String,Object>();
        myMap.put("icon",R.drawable.a9);
        myMap.put("name","時鐘");
        myMap.put("desc","時時刻刻,每分每秒都為你計算!");
        myList.add(myMap);
        return myList;
    }
} 
           

    7.3)主布局xml檔案custom_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<ListView
    android:id="@+id/custom_adapter_lv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

</ListView>
</LinearLayout>   
           

    7.4)單個item布局檔案custom_adapter_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="85dp"
        android:layout_height="85dp"
        android:id="@+id/custom_icon" />
    <RelativeLayout
        android:layout_alignBaseline="@+id/custom_icon"
        android:layout_toRightOf="@+id/custom_icon"
        android:id="@+id/tv_rLayout"
        android:orientation="vertical"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/name" />

        <TextView
            android:layout_marginTop="10dp"
            android:layout_below="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"
            android:id="@+id/desc"
            android:singleLine="true"
            android:ellipsize="end"
            />

    </RelativeLayout>
    <Button
        android:layout_marginTop="10dp"
        android:layout_marginRight="10dp"
        android:layout_alignParentRight="true"
        android:id="@+id/download"
        android:text="下載下傳"
        android:textColor="#fff"
        android:textSize="14sp"
        android:background="@color/colorAccent"
        android:layout_width="60dp"
        android:layout_height="30dp" />

</RelativeLayout> 
           

    7.5)效果截圖

Android Composite(ListView)詳解

8.下拉重新整理,上拉加載(SwipeRefreshLayout(google官方下來重新整理元件)+自定義上拉加載更多)

    8.1)自定義ListView類PullRefreshListView.java

package com.example.listview;

import android.content.Context;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;

/**
 * Created by elimy on 2016-08-29.
 */
public class PullRefreshListView extends ListView implements AbsListView.OnScrollListener{

    //底部加載更多的控件
    private View footerView;
    //底部重新整理高度
    private int footerHeight;
    //辨別是否滑動到底部
    private boolean isScrollToBottom = false;
    //辨別是否正在加載
    private boolean isRefreshing = false;
    //對ListView的下拉和上拉重新整理進行監聽的變量
    private OnRefreshListener myOnRefreshListener;

    /*
    帶一個參數的構造函數
    * */
    public PullRefreshListView(Context context) {
        super(context);
    }
    /*
    * 帶兩個參數的構造函數
    * */
    public PullRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //通過View.inflate()初始化自定義的底部重新整理View
            footerView = View.inflate(getContext(),R.layout.footer_view,null);
            Log.d("footer_view",footerView.toString()+"");
        //測繪footerView
        if (footerView != null){
            footerView.measure(0,0);
            //擷取底部控件高度并初始化
            footerHeight = footerView.getMeasuredHeight();
            //剛開始隐藏footerView
            footerView.setPadding(0, -footerHeight, 0, 0);
            //添加footerView到ListView
            this.addFooterView(footerView);
            //為初始化的PullRefreshListView設定監聽
            this.setOnScrollListener(this);
        }else {
            Log.d("footerView_debug","footerView is null");
        }

    }
    /*
    * 開放監聽器接口,友善在使用的時候為自定義的PullRefreshListView添加監聽并實作監聽後的操作
    * */
    public void setOnRefreshListener(OnRefreshListener onRefreshListener){
        myOnRefreshListener =onRefreshListener;
    }
    /*
    * 實作隐藏方法,提供給使用的類在加載完後隐藏footerView
    * */
    public void hideFooterView (){
        footerView.setPadding(0, -footerHeight, 0, 0);
        isRefreshing=false;
    }
    /*
    *scroll狀态改變的監聽,繼承至AbsListView.OnScrollListener
    * */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_FLING || scrollState == SCROLL_STATE_IDLE){
            if (!isRefreshing && isScrollToBottom){
              isRefreshing = true;
                //顯示出footerView
                footerView.setPadding(0,0,0,0);
                //設定選中可見item的最後一項
                this.setSelection(this.getCount());
                if (myOnRefreshListener != null){
                    myOnRefreshListener.refreshData();
                }
            }
        }
    }
    /*
    * 對ListView正在滾動進行監聽
    * */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        int endItemPosition =totalItemCount-1;
        if (endItemPosition==getLastVisiblePosition()){
            isScrollToBottom =true;
        }else {
            isScrollToBottom = false;
        }
    }
    /*
    * 自定義一個接口供外界調用實作上拉重新整理資料
    * */
    public interface OnRefreshListener{
        void refreshData();
    }
}
           

    8.2)底部重新整理view xml布局footer_view.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <RelativeLayout
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
       android:layout_width="match_parent"
        android:layout_height="wrap_content">
    <ProgressBar
        android:layout_toLeftOf="@+id/refresh_tv"
        android:id="@+id/refresh_pgbar"
        android:layout_marginTop="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleSmall" />
        <TextView

            android:id="@+id/refresh_tv"
            android:text="正在加載資料..."
            android:textSize="20dp"
            android:gravity="center"
            android:layout_centerHorizontal="true"
            android:layout_alignBaseline="@+id/refresh_pgbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </RelativeLayout>
</LinearLayout>
           

    8.3)主activity類PullRefreshActivity.java

package com.example.listview;

import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;

import java.util.ArrayList;



/**
 * Created by elimy on 2016-08-29.
 */
public class PullRefreshActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener,PullRefreshListView.OnRefreshListener {
    private SwipeRefreshLayout swipeRefreshLayout;
    private PullRefreshListView pullRefreshListView;
    private ArrayAdapter myAdapter;
    private ListItems listItems;
    private  ArrayList<String> firstItems;
    //辨別下拉是否正在重新整理
    private boolean isRefresh = false;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.refresh_listview);
        //初始化控件
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
        pullRefreshListView = (PullRefreshListView) findViewById(R.id.custom_refresh_lv);
        //設定監聽器
        swipeRefreshLayout.setOnRefreshListener(this);
        pullRefreshListView.setOnRefreshListener(this);
        //初始化資料類
        listItems = new ListItems();
        firstItems = listItems.getFirstData();
        myAdapter = new ArrayAdapter(this,android.R.layout.simple_expandable_list_item_1,firstItems);
        pullRefreshListView.setAdapter(myAdapter);


        //設定圓圈進度條的背景顔色
       swipeRefreshLayout.setProgressBackgroundColorSchemeColor(
                getResources().getColor(R.color.white));

        //設定進度條變化的顔色
        swipeRefreshLayout.setColorSchemeResources(
                R.color.colorAccent,
                R.color.purple
                );
        //設定加載圓圈大小
        swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE);
        //設定下拉多少距離開始觸發重新整理
        swipeRefreshLayout.setDistanceToTriggerSync(200);

    }

    /*
        * 繼承自定義的PullRefreshListView的内部接口OnRefreshListener
        * 實作上拉加載資料的操作
        *
        * */
    @Override
    public void refreshData() {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                ArrayList<String> bottomData = listItems.getBottomRefreshData();
                firstItems.addAll(bottomData);
                //通知資料改變
                myAdapter.notifyDataSetChanged();
                //隐藏footerView,停止更新
                pullRefreshListView.hideFooterView();
            }
        },5000);

    }
    /*
    * 繼承SwipeRefreshLayout.OnRefreshListener的方法
    * 實作下拉重新整理操作
    * */
    @Override
    public void onRefresh() {
        if (!isRefresh)
        {
            isRefresh =true;
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    ArrayList<String> startData = listItems.getStartData();
                    firstItems.addAll(0,startData);
                    //通知資料改變
                    myAdapter.notifyDataSetChanged();
                    isRefresh =false;
                    //設定隐藏或者顯示重新整理進度圓圈
                    swipeRefreshLayout.setRefreshing(false);
                }
            },5000);
        }
    }
}  
           

    8.4)主布局檔案refresh_listview.xml  

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.example.listview.PullRefreshListView
            android:id="@+id/custom_refresh_lv"
          android:layout_width="match_parent"
          android:layout_height="match_parent">

      </com.example.listview.PullRefreshListView>
    </android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
           

    8.5)資料構造類ListItems.java

package com.example.listview;

import java.util.ArrayList;

/**
 * Created by elimy on 2016-08-29.
 */
public class ListItems {
    public ArrayList<String> getBottomRefreshData(){
       ArrayList<String> list = new ArrayList<String>();
        for (int i = 1;i<=5;i++){
            list.add("上拉重新整理資料"+i);
        }
        return list;
    }
    public ArrayList<String> getFirstData(){
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 1;i<=5;i++){
            list.add("初始資料"+i);
        }
        return list;
    }
    public ArrayList<String> getStartData(){
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 1;i<=5;i++){
            list.add("下拉重新整理資料"+i);
        }
        return list;
    }
}
           

    8.6)效果截圖

        依次為沒做操作效果,下拉重新整理中效果,上拉加載更多中效果(不會做gif動圖真是淡疼)

Android Composite(ListView)詳解
Android Composite(ListView)詳解
Android Composite(ListView)詳解

  推薦文章:

             http://www.lai18.com/content/3281354.html

             http://www.jianshu.com/p/97ab87cfce47

             https://github.com/android-cjj/BeautifulRefreshLayout