天天看點

AdapterView及子類(一)AdapterView及子類

AdapterView及子類

AdapterView是一組重要的元件,AdapterView本身是一個抽象基類,它派生的子類在用法上十分相似,隻是顯示界面有一定的差別。

AdapterView具有如下特征

  • AdapterView繼承ViewGrop,它的本質是容器
  • AdapterView可以包括多個"清單項"并将多個"清單項"以合适的形式顯示出來
  • AdapterView 顯示的多個"清單項"由Adapter提供。調用AdapterView的setAdapter(Adapter)的方法設定Adapter即可。

    AdapterView及其子類的繼承關系圖如下圖所示

    AdapterView及子類(一)AdapterView及子類
    由上圖可以看出AdapterView派生了三個子類:AbsListView、AbsSpinner和AdapterViewAnimator,這三個子類依然是抽象的,實際使用往往采用它們的子類。
由于Gallery是一個過時的API,Android推薦使用HorizonatalScrollViewl來代替它。

ListView介紹

ListView是手機系統中使用非常廣泛的一種元件,它以垂直清單的形式顯示所有清單項,生成清單視圖的兩種方式:

- 直接使用ListView建立

- 讓Activity繼承ListActivity(相當于該Activity顯示的元件為ListView)

程式擷取ListView後,接下來就需要為ListView設定顯示的清單項了,通過setAdapter()方法為之提供Adapter,并由Adapter提供清單項即可。

AbsListView提供的常用XML屬性及相關方法:

XML屬性 相關方法 說明
Android:choiceMode 設定說明AbsListView的選擇行為。該屬性支援以下屬性值 none :不顯示任何選中項 singleChoice:允許單選 multipleChoice:允許多選 multipleChoiceModal:允許多選
Android:drawSelectorOnTop setDrawSelectorOnTop(boolean) 如果屬性設定為true,選中的清單項将會顯示在上面
Android:fastScorllEnabled 設定是否允許快速滾動。true将會顯示滾動圖示,并允許使用者拖動該滾動圖示進行快速滾動
Android:listSelector setSelector(int) 指定被選中的清單項上繪制的Drawable
android:scorllingCache 如果設定為true,該元件在滾動時會使用繪制緩存
android:smoothScrollbar setSmoothScrollbarEnabled(boolean) 如果設定為false,則不在headerView之後繪制分割條
android:stackFromBottom 設定是否從底端開始排列清單項
android:textFilterEnabled 設定是否對清單進行過濾。當該AbsListView對應的Adapter實作了Filter接口時該屬性才起作用
android:transcriptMode 設定該元件的滾動模式。該屬性有如下屬性值:disabled:關閉滾動。這是預設值 normal:當該AbsListView收到資料改變通知,且最後一個清單項可見時,該AbsListView将會滾動到底端 alwaysScrool:該AbsListView總會自動滾動到底端

ListView提供的常用XML屬性:

XML屬性 說明
android:divider 設定List清單項的分隔條(既可用顔色分隔,也可用Drawable分隔)
android:dividerHeight 設定分隔條的高度
android:entries 指定一個數組資源,Android将根據數組資源來生成ListView
android:footerDividerEnabled 如果設定為false,則不在footerView之後繪制分隔條
android:headerDividerEnabled 如果設定為false,則不在headerView之後繪制分隔條

執行個體

在界面布局activity_main檔案中添加個ListView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!--直接使用數組資源給出清單項-->
    <!--使用紅色分隔條,高度2px-->
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:divider="#f00"
        android:dividerHeight="2px"
        android:entries="@array/books"
        />
</androidx.constraintlayout.widget.ConstraintLayout>
           

上面的界面布局中定義了一個ListView,并通過android:entries指定了清單項數組。還利用了android:divider屬性設定分隔條的顔色為紅色,android:dividerHeight設定了分隔條的高度為2px

ListView指定了android:entries="@array/books",該屬性值用到了數組資源,是以還需定義一個名為books的數組,定義數組資源檔案如下:

values\arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="books">
        <item>Java</item>
        <item>Html</item>
        <item>Android</item>
        <item>C++</item>
        <item>JQuery</item>
    </string-array>
</resources>
           

效果圖:

AdapterView及子類(一)AdapterView及子類

Adapter接口

Adapter本身隻是一個接口,它派生了ListAdapter和SpinnerAdapter兩個子接口,其中ListAdapter為AbsListView提供清單項,而SpinnerAdapter為AbsSpinner提供清單項。

Adapter接口及其實作類的繼承關系如圖所示:

AdapterView及子類(一)AdapterView及子類

常用的Adapter:BaseAdapter、ArrayAdapter、SimpleAdapter、SimpleCursorAdapter。

從上圖可以看出,幾乎所有的Adapter都繼承了BaseAdapter,而BaseAdapter同時實作了ListAdapter、SpinnerAdapter兩個接口,是以BaseAdapter及其子類可以同時為了AbsListView、AbsSpinner提供清單項。

Adapter常用的實作類如下:

  • ArrayAdapter:簡單、易用的Adapter,通常用于數組或List集合的多個值包裝成多個清單項。
  • SimpleAdapter:并不簡單、功能強大的Adapter,可用于将List集合的多個對象包裝成多個清單項。
  • SimpleCursorAdapter:與SimpleAdapter基本相似,隻是用于包裝Cursor提供的資料。
  • BaseAdapter:通常用于被擴充。擴充BaseAdapter可以對各清單項進行最大限度的定制。

執行個體

1.通過ArrayAdapter來實作Adapter

布局檔案activity.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <!--使用紅色分隔條-->
    <ListView
        android:id="@+id/list1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:divider="#f00"
        android:dividerHeight="2px"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.094" />

</androidx.constraintlayout.widget.ConstraintLayout>
           

MainActivity.java檔案

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*初始化ListView*/
        ListView list1 = findViewById(R.id.list1);
        /*定義一個數組*/
        String[] arr1 = new String[]{"Java","Android","C++"};
        /*将數組包裝成為ArrayAdapter*/
        ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this,R.layout.array_item,arr1);
        /*為第一個ListView設定Adapter*/
        list1.setAdapter(adapter1);


    }
}

           

上面代碼,有一步驟就是把數組包裝成ArrayAdapter對象,也就是建立ArrayAdapter對象,建立ArrayAdapter時必須指定如下參數。

  • Context:上下文,代表通路整個Android應用的接口。
  • textViewResourceId:一個資源的ID,該資源的ID代表一個TextView,該TextView元件将作為ArrayAdapter的清單元件
  • 數組或List:該數組或List将負責為多個清單項提供資料

建立ArrayAdapter對象中的布局檔案 array_item.xml代碼如下

<?xml version="1.0" encoding="utf-8"?>
<TextView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="30sp"
        android:text="TextView" />

           

效果圖

AdapterView及子類(一)AdapterView及子類

通過以上内容可以看出,數組或List包含多少個元素就會生成多少個清單項,每個清單項都是TextView元件,TextView元件顯示的文本由數組或List提供,而array_item.xml檔案就是負責每個清單項的元件外觀。

2.基于ListActivity實作清單

如果程式的視窗僅僅需要顯示一個清單,則可以直接讓Activity繼承ListActivity來實作,ListActivity的子類無須調用setContentView()方法顯示某個界面,而是直接傳入一個内容Adapter,ListActivity的子類就呈現一個清單。

MainActivity.java檔案

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;


public class MainActivity extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //無須布局檔案
        String[] arr = new String[]{"JAVA","Android","C++"};
        //建立ArrayAdapter對象
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.array_item,arr);
        //設定視窗顯示清單
        setListAdapter(adapter);
    }
}

           

上面程式Activity繼承ListActivity,ListActivity無須界面布局檔案——相當于它的布局檔案隻有一個ListView,是以隻要為ListActicity設定Adapter即可

3.使用SimpleAdapter建立ListView

使用ArrayAdapter實作Adapter雖然簡單、易用,但ArrayAdapter的功能比較有限,它的每個清單項隻能是TextView。如果需要更複雜的清單項,則可以考慮使用SimpleAdapter,SimpleAdapter,功能非常強大,ListView的大部分應用場景,都可以通過SimpleAdapter實作。

界面布局檔案:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <!--使用紅色分隔條-->
    <ListView
        android:id="@+id/list1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />
</androidx.constraintlayout.widget.ConstraintLayout>
           

Activity代碼

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

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

public class MainActivity extends AppCompatActivity {
    private String[] platfroms = new String[]{"eclipse","webstorm","as"};
    private String[] languages = new String[]{"JAVA","HTML","ANDROID"};
    private int[]  images = new int[]{R.drawable.eclipse,R.drawable.webstorm,R.drawable.studio};
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*初始化listView*/
        listView = findViewById(R.id.list);
        /*建立一個List集合,List集合的元素是Map*/
        List<Map<String,Object>> maplist = new ArrayList<Map<String, Object>>();
        for(int i=0;i<platfroms.length;i++){
            Map<String,Object> map = new HashMap<String, Object>();
            map.put("image",images[i]);
            map.put("platfroms",platfroms[i]);
            map.put("languages",languages[i]);
            maplist.add(map);
        }
        /*建立一個SimpleAdapter*/
        SimpleAdapter simpleAdapter = new SimpleAdapter(this,maplist,R.layout.simple_item,new String[]{"image","platfroms","languages"},new int[]{R.id.sim_img,R.id.sim_tv1,R.id.sim_tv2});
        /*為ListView設定Adapter*/
        listView.setAdapter(simpleAdapter);
    }
}

           

建立SimpleAdapter對象需要五個參數:

  • 第一個參數:上下文。
  • 第二個參數:一個List<?extends Map<String,? >>類型的集合對象,該集合中的每個Map<String,? >對象生成一個清單項。
  • 第三個參數:該參數指定一個界面布局的ID。
  • 第四個參數:該參數應該是個String[]類型的參數,該參數決定提取Map<String,? >對象中那些key對應的Value來生成清單項
  • 第五個參數:該參數應該是個int[] 類型的參數,該參數決定填充那些元件

清單項布局檔案simple_item.xml

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


        <ImageView
            android:id="@+id/sim_img"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:scaleType="centerInside"
            app:srcCompat="@android:drawable/sym_def_app_icon" />

       <LinearLayout
           android:layout_width="0dp"
           android:layout_height="match_parent"
           android:layout_weight="3"
           android:orientation="vertical">

           <TextView
               android:id="@+id/sim_tv1"
               android:layout_width="wrap_content"
               android:layout_height="0dp"
               android:layout_weight="2"
               android:textSize="20sp"
               android:gravity="center"
               android:text="TextView" />

           <TextView
               android:id="@+id/sim_tv2"
               android:layout_width="wrap_content"
               android:layout_height="0dp"
               android:layout_weight="1"
               android:gravity="center"
               android:textSize="15sp"
               android:text="TextView" />
       </LinearLayout>
    </LinearLayout>

</LinearLayout>
           

效果圖:

AdapterView及子類(一)AdapterView及子類
SimpleAdapter同樣可以作為ListActivity的内容Adapter。

如果需要監聽使用者單擊、選中某個清單項的事件,則可以通過AdapterView的setOnItemClickListener()方法為單擊事件添加監聽器,或者通過setOnItemSelectedListener()方法為清單項的選中事件添加監聽器。

/*為listView的清單項添加單擊事件監聽器*/
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                System.out.println(platfroms[i]+"被單擊");
            }
        });
        /*為listView的清單項添加選中事件監聽器*/
        listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                System.out.println(platfroms[i]+"被選中");
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });


           

LogCat控制台輸出

AdapterView及子類(一)AdapterView及子類