Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Composite(ListView)詳解

Android Composite(ListView)詳解

編輯:關於Android編程

目錄:
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 list;
    private ArrayAdapter 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();
        for (int i= 1;i<20;i++){
            list.add("數據"+i);
        }
        //初始化適配器
        //Context:表示當前context及MainActivity.this
        // int resource:單條數據顯示布局
        // List objects:ArrayList數據集合
        arrayAdapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1,list);
        //設置適配器
        listView.setAdapter(arrayAdapter);
    }

} 


4.2)主布局文件activity_main.xml


    





4.3)效果截圖
\
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





    


5.3)單個item xml文件simple_cursor_item.xml



    
 

注意:訪問聯系人需要注冊權限:

5.4)效果截圖
\
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> myList;
    private HashMap 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> getMyList(){
        //實例化帶泛型ArrayList
        myList =new ArrayList>();
        //初始化HashMap
        myMap = new HashMap();
        //放入數據,這裡就直接put,如果有數據庫讀取數據可以將cursor類型數據轉換成map類型
        myMap.put("icon",R.drawable.a2);
        myMap.put("name","支付寶");
        myMap.put("desc","支付寶支付為大家!");
        myList.add(myMap);
        //第二條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a3);
        myMap.put("name","google浏覽器");
        myMap.put("desc","想看啥看啥!");
        myList.add(myMap);
        //第三條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a7);
        myMap.put("name","米聊");
        myMap.put("desc","和女神面對面!");
        myList.add(myMap);
        //第四條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a8);
        myMap.put("name","指南針");
        myMap.put("desc","想去哪兒,就去哪兒!");
        myList.add(myMap);
        //第五條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a9);
        myMap.put("name","時鐘");
        myMap.put("desc","時時刻刻,每分每秒都為你計算!");
        myList.add(myMap);
        return myList;
    }
}


6.2)主布局simple_adapter.xml


    

    


6.3)單個item xml布局simple_adapter_item.xml



    
    
        

        

    


6.4)效果截圖
\
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> list;
    private LayoutInflater inflater;
    /*
    * 帶參數構造方法
    * Context:指實例化CustomAdapter的上下文
    * ArrayList:表示需要適配的數據源
    * */
    public CustomAdapter(Context context, ArrayList> 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> myList;
    private Map 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> list =getMyList();
        //實例化自定義適配器
        customAdapter = new CustomAdapter(BaseAdapterActivity.this,list);
        //設置適配器
        customAdapterListView.setAdapter(customAdapter);
    }
    /*
    * 封裝方法初始化數據
    * */
    public ArrayList> getMyList(){
        //實例化帶泛型ArrayList
        myList =new ArrayList>();
        //初始化HashMap
        myMap = new HashMap();
        //放入數據,這裡就直接put,如果有數據庫讀取數據可以將cursor類型數據轉換成map類型
        myMap.put("icon",R.drawable.a2);
        myMap.put("name","支付寶");
        myMap.put("desc","支付寶支付為大家!");
        myList.add(myMap);
        //第二條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a3);
        myMap.put("name","google浏覽器");
        myMap.put("desc","想看啥看啥!");
        myList.add(myMap);
        //第三條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a7);
        myMap.put("name","米聊");
        myMap.put("desc","和女神面對面!");
        myList.add(myMap);
        //第四條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a8);
        myMap.put("name","指南針");
        myMap.put("desc","想去哪兒,就去哪兒!");
        myList.add(myMap);
        //第五條數據
        myMap = new HashMap();
        myMap.put("icon",R.drawable.a9);
        myMap.put("name","時鐘");
        myMap.put("desc","時時刻刻,每分每秒都為你計算!");
        myList.add(myMap);
        return myList;
    }
} 


7.3)主布局xml文件custom_adapter.xml





   


7.4)單個item布局文件custom_adapter_item.xml



    
    
        

        

    


7.5)效果截圖
\
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




    
    
        
    


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 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 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 startData = listItems.getStartData();
                    firstItems.addAll(0,startData);
                    //通知數據改變
                    myAdapter.notifyDataSetChanged();
                    isRefresh =false;
                    //設置隱藏或者顯示刷新進度圓圈
                    swipeRefreshLayout.setRefreshing(false);
                }
            },5000);
        }
    }
}  


8.4)主布局文件refresh_listview.xml



    

        

      
    


8.5)數據構造類ListItems.java
package com.example.listview;

import java.util.ArrayList;

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


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

\\ \


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved