Carson帶你學Android:ListView與AdapterView全面解析

前言

  • ListViewAndroid開發中十分常見
  • 今天,我將為大家帶來ListViewAdapterView全面解析,含其特點、工作原理等,希望你們會喜歡。

目錄

示意圖

1. 簡介

  • Android中的一種列表視圖組件
  • 繼承自AdapterView抽象類,類圖關系如下
示意圖

2. 作用

集合多個 “項”(稱為:Item) & 以列表的形式 展示

示意圖

3. 工作原理

3.1 本質原理

  • ListView僅作為容器(列表),用于裝載 & 顯示數據(即 列表項Item
  • 而容器內的具體數據(列表項Item)則是由 適配器(Adapter)提供

適配器(Adapter):作為View 和 數據之間的橋梁 & 中介,將數據映射到要展示的View

  • 當需顯示數據時,ListView會向Adapter取出數據,從而加載顯示,具體如下圖
示意圖
  • 結論
    ListView負責以列表的形式顯示Adapter提供的內容

3.2 緩存原理

試想一個場景:若把所有數據集合的信息都加載到ListView上顯示,若 ListView要為每個數據都創建一個視圖,那么會占用非常多的內存

  • 為了節省空間和時間,ListView不會為每一個數據創建一個視圖,而是采用了Recycler組件,用于回收 & 復用 View

  • 當屏幕需顯示xItem時,那么ListView會創建 x+1個視圖;當第1個Item離開屏幕時,此ItemView被回收至緩存,入屏的ItemView會優先從該緩存中獲取

注:

  1. 只有Item完全離開屏幕后才可復用,這也是為什么ListView要創建比屏幕需顯示視圖多1個的原因:緩沖 顯示視圖
  2. 即:第1個Item離開屏幕是有過程的,會有1個 第1個Item的下半部分 & 第8個Item上半部分同時在屏幕中顯示的狀態,此時仍無法使用緩存的View,只能繼續用新創建的視圖View
  • 實例演示
    設:屏幕只能顯示5個Item,那么ListView只會創建(5+1)個Item的視圖;當第1個Item完全離開屏幕后才會回收至緩存從而復用(用于顯示第7個Item
示意圖

4. 具體使用

1. 生成方式

生成列表視圖(ListView)的方式主要有兩種:

  • 直接用ListView進行創建
  • 讓Activity繼承ListActivity

2. xml文件配置信息

<LinearLayout 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:background="#FFE1FF"   
    android:orientation="vertical" >   
    <ListView   
        android:id="@+id/listView1"   
        android:layout_width="match_parent"   
        android:layout_height="match_parent" />   
</LinearLayout>  

AbsListView的常用屬性和相關方法:

屬性 說明 備注
android:choiceMode 列表的選擇行為,默認:none沒有選擇行為 選擇方式: none:不顯示任何選中項 singleChoice:允許單選multipleChoice:允許多選multipleChoiceModal:允許多選 (把Activity里面adapter的第二個參數改成支持選擇的布局)
android:drawSelectorOnTop 如果該屬性設置為true,選中的列表項將會顯示在上面
android:listSelector 為點擊到的Item設置圖片 如果該屬性設置為true,選中的列表項將會顯示在上面
android:fastScrollEnabled 設置是否允許快速滾動 如果該屬性設置為true,將會顯示滾動圖標,并允許用戶拖動該滾動圖標進行快速滾動。
android:listSelector 指定被選中的列表項上繪制的Drawable
android:scrollingCache 滾動時是否使用緩存 如果設置為true,則在滾動時將會使用緩存
android:stackFromBottom 設置是否從底端開始排列列表項
android:transcriptMode 指定列表添加新的選項的時候,是否自動滑動到底部,顯示新的選項。 disabled:取消transcriptMode模式;默認的normal:當接受到數據集合改變的通知,并且僅僅當最后一個選項已經顯示在屏幕的時候,自動滑動到底部。 alwaysScroll:無論當前列表顯示什么選項,列表將會自動滑動到底部顯示最新的選項。

Listview提供的XML屬性:

XML屬性 說明 備注
android:divider 設置List列表項的分隔條(可用顏色分割,也可用圖片(Drawable)分割 不設置列表之間的分割線,可設置屬性為@null
android:dividerHeight 用于設置分隔條的高度
android:background屬性 設置列表的背景
android:entries 指定一個數組資源,Android將根據該數組資源來生成ListView
android:footerDividerEnabled 如果設置成false,則不在footer View之前繪制分隔條
andorid:headerDividerEnabled 如果設置成false,則不再header View之前繪制分隔條

5. Adapter簡介

Adapter本身是一個接口,Adapter接口及其子類的繼承關系如下圖:

Adapter接口及其子類的繼承關系.png
  • Adapter接口派生了ListAdapter和SpinnerAdapter兩個子接口

其中ListAdapter為AbsAdapter提供列表項,而SpinnerAdapter為AbsSpinner提供列表項

  • ArrayAdapter、SimpleAdapter、SimpleCursorAdapter、BaseAdapter都是常用的實現適配器的類
  1. ArrayAdapter:簡單、易用的Adapter,用于將數組綁定為列表項的數據源,支持泛型操作
  2. SimpleAdapter:功能強大的Adapter,用于將XML中控件綁定為列表項的數據源
  3. SimpleCursorAdapter:與SimpleAdapter類似,用于綁定游標(直接從數據數取出數據)作為列表項的數據源
  4. BaseAdapter:可自定義ListView,通用用于被擴展。擴展BaseAdapter可以對各個列表項進行最大程度的定制。

6. 常用適配器介紹

6.1 ArrayAdapter

定義
簡單、易用的Adapter,用于將數組綁定為列表項的數據源,支持泛型操作

步驟
1. 在xml文件布局上實現ListView

<?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.carson_ho.adapte_demo.MainActivity">   
 <ListView        
  android:id="@+id/list_item"        
  android:layout_width="match_parent"        
  android:layout_height="match_parent"        
  android:divider="#f00"        
  android:dividerHeight="1sp"        
  android:headerDividersEnabled="false">        
</ListView>
</RelativeLayout>
效果圖.png

2. 在MainActivity上定義一個鏈表,將所要展示的數據以存放在里面
3. 構造ArrayAdapter對象,設置適配器
4. 將LsitView綁定到ArrayAdapter上
如下圖:

public class MainActivity extends AppCompatActivity {     


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       ListView listView = (ListView) findViewById(R.id.list_item);
        //定義一個鏈表用于存放要顯示的數據
        final List<String> adapterData = new ArrayList<String>();
        //存放要顯示的數據
        for (int i = 0; i < 20; i++) {
            adapterData.add("ListItem" + i);
        }
        //創建ArrayAdapter對象adapter并設置適配器
         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, adapterData);
        //將LsitView綁定到ArrayAdapter上
        listView.setAdapter(adapter);
    }
}

創建ArrayAdapter對象要指定三個參數:

  • context:代表方位Android應用的接口
  • textViewRseourceld:資源ID,代表一個TextView
  • 數組:列表項展示的數據

5. 在xml文件布局添加資源文件TextView,該TextView組件將作列表項的組件

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

<TextView xmlns:android="http://schemas.android.com/apk/res/android"    
android:layout_width="match_parent"    
android:layout_height="wrap_content">
android:textSize="24sp"
</TextView>

最終效果圖

最終效果圖.png

缺點
ArrayAdapter較為簡單,易用,但每個列表項只能是TextView,功能實現的局限性非常大。

6.2 SimpleAdapter

  • 定義:功能強大的Adapter,用于將XML中控件綁定作為列表項的數據源
  • 特點:可對每個列表項進行定制(自定義布局),能滿足大多數開發的需求場景,靈活性較大

步驟
1. 在xml文件布局上實現ListView

<?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.carson_ho.adapte_demo.MainActivity">   
 <ListView        
  android:id="@+id/list_item"        
  android:layout_width="match_parent"        
  android:layout_height="match_parent"        
  android:divider="#f00"        
  android:dividerHeight="1sp"        
  android:headerDividersEnabled="false">        
</ListView>
</RelativeLayout>

2. 根據實際需求定制列表項:實現ListView每行的xml布局(即item布局)

<?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">        

<TextView            
android:id="@+id/name"            
android:layout_width="wrap_content"            
android:layout_height="wrap_content"            
android:textSize="17sp"            
android:paddingLeft="14dp"/>        
<TextView            
android:id="@+id/address"            
android:layout_below="@id/name"            
android:textSize="17sp"            
android:layout_width="wrap_content"            
android:layout_height="wrap_content" />        
<TextView            
android:id="@+id/lowerest_wholesale"            
android:layout_toRightOf="@id/address"            
android:textSize="17sp"            
android:layout_width="wrap_content"            
android:layout_height="wrap_content" />        
<TextView            
android:id="@+id/price"            
android:textSize="17sp"            
android:layout_below="@id/address"            
android:layout_width="wrap_content"            
android:layout_height="wrap_content" />        
<ImageView            
android:id="@+id/picture"            
android:layout_alignParentRight="true"            
android:layout_width="115dp"            
android:layout_height="86dp"         />        
</RelativeLayout>

3. 定義一個HashMap構成的列表以鍵值對的方式存放數據
4. 構造SimpleAdapter對象,設置適配器
5. 將LsitView綁定到SimpleAdapter上

public class MainActivity extends AppCompatActivity {
//定義數組以填充數據
    private String[] name=new String[]{            
"威龍注塑機","霸龍注塑機","恐龍注塑機"    };    
    private String[] address =new String[]{        
"廣東","北京","黑龍江"    };    
    private int[] lowerest_wholesale =new int[]{            
11,22,33    };    
    private int[] price =new int[]{            
11,22,33    };    
    private int[] picture =new int[]{
            R.drawable.home_selected,
            R.drawable.home_selected, 
            R.drawable.home_selected   };    

@Override    
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);   
         setContentView(R.layout.activity_main);

//定義一個HashMap構成的列表以鍵值對的方式存放數據
ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,Object>>();        
//循環填充數據   
for(int i=0;i<name.length;i++)        { 
HashMap<String,Object> map = new HashMap<String,Object>();            
map.put("name", name[i]);            
map.put("address", address[i]);            
map.put("lowerest_wholesale", lowerest_wholesale[i]);            
map.put("price", price[i]);            
map.put("picture", picture[i]);            
listItem.add(map);       
 }        

//構造SimpleAdapter對象,設置適配器        
SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,
listItem,//需要綁定的數據                
R.layout.item_imformation,//每一行的布局                
new String[] {"name","address", "lowerest_wholesale","price","picture"},
//數組中的數據源的鍵對應到定義布局的View中                
new int[] {R.id.name,R.id.address,R.id.lowerest_wholesale,R.id.price,R.id.picture});        
ListView list= (ListView) findViewById(R.id.list_item);        
//為ListView綁定適配器        
list.setAdapter(mSimpleAdapter);   
   }
}

結果顯示

結果顯示

6.3 BaseAdapter

定義
可自定義ListView,通用用于被擴展。擴展BaseAdapter可以對各個列表項進行最大程度的定制

使用步驟:

  1. 定義主xml布局
  2. 根據需要定義ListView每行所實現的xml布局
  3. 定義一個Adapter類繼承BaseAdapter,重寫里面的方法。
  4. 定義一個HashMap構成的列表,將數據以鍵值對的方式存放在里面。
  5. 構造Adapter對象,設置適配器。
  6. 將LsitView綁定到Adapter上。

先定義一個Adapter類繼承BaseAdapter,并重寫里面的方法

使用BaseAdapter必須寫一個類繼承它,同時BaseAdapter是一個抽象類,繼承它必須實現它的方法。

class MyAdapter extends BaseAdapter {
    private LayoutInflater mInflater;//得到一個LayoutInfalter對象用來導入布局

 //構造函數
    public MyAdapter(Context context,ArrayList<HashMap<String, Object>> listItem) {
        this.mInflater = LayoutInflater.from(context);
        this.listItem = listItem;
    }//聲明構造函數

    @Override
    public int getCount() {
        return listItem.size();
    }//這個方法返回了在適配器中所代表的數據集合的條目數

    @Override
    public Object getItem(int position) {
        return listItem.get(position);
    }//這個方法返回了數據集合中與指定索引position對應的數據項

    @Override
    public long getItemId(int position) {
        return position;
    }//這個方法返回了在列表中與指定索引對應的行id


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }//這個方法返回了指定索引對應的數據項的視圖,還沒寫完
}

這里主要講一下BaseAdapter里必須要重寫的4個方法

  • BaseAdapter的靈活性就在于它要重寫很多方法,其中最重要的即為getView()方法。
  • 我們結合上述重寫的4個方法了解ListView的繪制過程:
示意圖

其中,重點講解重寫的getView()方式,總共有3種


/**
  * 重寫方式1:直接返回了指定索引對應的數據項的視圖
  */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View item = mInflater.inflate(R.layout.item,null);
        ImageView img = (ImageView)item.findViewById(R.id.ItemImage);
        TextView title = (TextView)item.findViewById(R.id.ItemTitle);
        TextView test = (TextView)item.findViewById(R.id.ItemText);
        Button btn = (Button) item.findViewById(R.id.ItemBottom);
        img.setImageResource((Integer) listItem.get(position).get("ItemImage"));
        title.setText((String) listItem.get(position).get("ItemTitle"));
        test.setText((String) listItem.get(position).get("ItemText"));

        return item;
    }
    // 缺點:
    // 每次調用getView()時,都要重新通過 findViewById() 尋找View組件 & 重新繪制View
    // 當列表項數據量很大時會嚴重影響性能,即體現為下拉很慢、卡

/**
  * 重寫方式2:使用convertView作為View緩存(優化)
  * 具體原理:
  *       // a. 將 convertView作為getView()的輸入參數 & 返回參數,從而形成反饋
  *       // b. 形成了Adapter的itemView重用機制,減少了重繪View的次數
  */
     @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // 檢測有無可重用的View,若無就重新繪制
        if(convertView == null)
        {
            convertView = mInflater.inflate(R.layout.item, null);
        }
        ImageView img = (ImageView)convertView.findViewById(R.id.ItemImage);
        TextView title = (TextView)convertView.findViewById(R.id.ItemTitle);
        TextView test = (TextView)convertView.findViewById(R.id.ItemText);
        Button btn = (Button) convertView.findViewById(R.id.ItemBottom);
        img.setImageResource((Integer) listItem.get(position).get("ItemImage"));
        title.setText((String) listItem.get(position).get("ItemTitle"));
        test.setText((String) listItem.get(position).get("ItemText"));

        return convertView;
        // 最終返回convertView形成反饋
    }

    // 優點:減少了重繪View的次數
    // 缺點:但是每次都要通過 findViewById() 尋找View組件

/**
  * 重寫方式3:在方式2的基礎上,使用ViewHolder實現更加具體的緩存:View組件緩存
  * 具體原理:
  *       // a. 將 convertView作為getView()的輸入參數 & 返回參數,從而形成反饋
  *       // b. 形成了Adapter的itemView重用機制,減少了重繪View的次數
  */
    static class ViewHolder

        {
            public ImageView img;
            public TextView title;
            public TextView text;
            public Button btn;
        }

    @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder ;
            if(convertView == null)
            {
                holder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.item, null);
                holder.img = (ImageView)convertView.findViewById(R.id.ItemImage);
                holder.title = (TextView)convertView.findViewById(R.id.ItemTitle);
                holder.text = (TextView)convertView.findViewById(R.id.ItemText);
                holder.btn = (Button) convertView.findViewById(R.id.ItemBottom);
                convertView.setTag(holder);
            }
            else {
                holder = (ViewHolder)convertView.getTag();

            }
            holder.img.setImageResource((Integer) listItem.get(position).get("ItemImage"));
            holder.title.setText((String) listItem.get(position).get("ItemTitle"));
            holder.text.setText((String) listItem.get(position).get("ItemText"));

            return convertView;
        }
  // 優點:重用View時就不用通過 findViewById()重新 尋找View組件,同時也減少了重繪View的次數,是ListView使用的最優化方案
  • 方案3(通過convertView+ViewHolder重寫getView())是ListView使用的最優化,所以非常推薦大家使用

  • 總結:ListView的優化

示意圖
  • 最優化方案的完整實現方案
  1. 定義主xml的布局
    activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="#FFFFFF"
    android:orientation="vertical" >
    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
  1. 根據需要,定義ListView每行所實現的xml布局(item布局)
    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_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/ItemImage"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按鈕"
        android:id="@+id/ItemBottom"
        android:focusable="false"
        android:layout_toLeftOf="@+id/ItemImage" />
    <TextView android:id="@+id/ItemTitle"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:textSize="20sp"/>
    <TextView android:id="@+id/ItemText"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_below="@+id/ItemTitle"/>
</RelativeLayout>
  1. 定義一個Adapter類繼承BaseAdapter,重寫里面的方法。

(利用convertView+ViewHolder來重寫getView())

MyAdapter.java

package scut.learnlistview;

import android.content.Context;
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 java.util.ArrayList;
import java.util.HashMap;

class MyAdapter extends BaseAdapter {
    private LayoutInflater mInflater;//得到一個LayoutInfalter對象用來導入布局 
    ArrayList<HashMap<String, Object>> listItem;

    public MyAdapter(Context context,ArrayList<HashMap<String, Object>> listItem) {
        this.mInflater = LayoutInflater.from(context);
        this.listItem = listItem;
    }//聲明構造函數

    @Override
    public int getCount() {
        return listItem.size();
    }//這個方法返回了在適配器中所代表的數據集合的條目數

    @Override
    public Object getItem(int position) {
        return listItem.get(position);
    }//這個方法返回了數據集合中與指定索引position對應的數據項

    @Override
    public long getItemId(int position) {
        return position;
    }//這個方法返回了在列表中與指定索引對應的行id

//利用convertView+ViewHolder來重寫getView()
    static class ViewHolder
    {
        public ImageView img;
        public TextView title;
        public TextView text;
        public Button btn;
    }//聲明一個外部靜態類
    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        ViewHolder holder ;
        if(convertView == null)
        {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.item, null);
            holder.img = (ImageView)convertView.findViewById(R.id.ItemImage);
            holder.title = (TextView)convertView.findViewById(R.id.ItemTitle);
            holder.text = (TextView)convertView.findViewById(R.id.ItemText);
            holder.btn = (Button) convertView.findViewById(R.id.ItemBottom);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder)convertView.getTag();

        }
        holder.img.setImageResource((Integer) listItem.get(position).get("ItemImage"));
        holder.title.setText((String) listItem.get(position).get("ItemTitle"));
        holder.text.setText((String) listItem.get(position).get("ItemText"));
        holder.btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("你點擊了選項"+position);//bottom會覆蓋item的焦點,所以要在xml里面配置android:focusable="false"
            }
        });

        return convertView;
    }//這個方法返回了指定索引對應的數據項的視圖
}

4.在MainActivity里:

  • 定義一個HashMap構成的列表,將數據以鍵值對的方式存放在里面。
  • 構造Adapter對象,設置適配器。
  • 將LsitView綁定到Adapter上。

MainActivity.java

package scut.learnlistview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ListView lv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lv = (ListView) findViewById(R.id.listView1);
        /*定義一個以HashMap為內容的動態數組*/
        ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();/*在數組中存放數據*/
        for (int i = 0; i < 100; i++) {
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("ItemImage", R.mipmap.ic_launcher);//加入圖片
            map.put("ItemTitle", "第" + i + "行");
            map.put("ItemText", "這是第" + i + "行");
            listItem.add(map);
        }
        MyAdapter adapter = new MyAdapter(this, listItem);
        lv.setAdapter(adapter);//為ListView綁定適配器

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                System.out.println("你點擊了第" + arg2 + "行");//設置系統輸出點擊的行
            }
        });

}
}

運行結果


點擊輸出結果:



注:進階使用 = 添加頭部 & 尾部View

在日常使用中,我們常常會需要在ListView頭部 / 尾部添加視圖

步驟1:添加頭部 / 尾部視圖

header_view.xml

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="header"
        android:textSize="20dp"
        android:gravity="center"/>

</LinearLayout>

步驟2:添加到ListView中

private ListView lv;

View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.header_view, null);

lv.addHeaderView(view);
// lv.addFooterView(view); // 添加到底部View

示意圖


7. 與RecylerView的區別

image.png

8. 總結

  • 本文全面介紹了 ListViewAdapterView
  • 下面我將繼續對 Android中的知識進行深入講解 ,感興趣的同學可以繼續關注Carson_Ho的簡書

相關系列文章閱讀
Carson帶你學Android:學習方法
Carson帶你學Android:四大組件
Carson帶你學Android:自定義View
Carson帶你學Android:異步-多線程
Carson帶你學Android:性能優化
Carson帶你學Android:動畫


歡迎關注Carson_Ho的簡書

不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度


請點贊!因為你的鼓勵是我寫作的最大動力!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容