做網(wǎng)站地圖的步驟網(wǎng)絡(luò)推廣優(yōu)化seo
目錄
Android 自定義 Adapter
Adapter 接口
SpinnerAdapter
ListAdapter
BaseAdapter
自定義 BaseAdapter
參考文檔
Android ListView 列表控件
ListView 的屬性和方法
表頭表尾分割線的設(shè)置
列表從底部開始顯示 android:stackFromBottom
設(shè)置點(diǎn)擊顏色 cacheColorHint
隱藏滑動條
Android 自定義 Adapter
在上一篇文章中我們知道了啥是 Adapter,也知道了 Adapter 的家族體系,也用過了幾個Adapter。
本篇文章,我們就來自己實(shí)現(xiàn)一個?Adapter。
要實(shí)現(xiàn)自定義的 Adapter,通常繼承自 BaseAdapter 類,并重寫其中的方法來適配你的數(shù)據(jù)源。
首先,我們要做的就是要了解我們到底要重寫哪些方法,因?yàn)?BaseAdapter 實(shí)現(xiàn)了 ListAdapter 和 SpinnerAdapter 接口,而這兩個接口又繼承自 Adapter
Adapter 接口
打開?Adapter?API 文檔,我們可以看到它有以下幾個方法要實(shí)現(xiàn)
這些方法的說明如下:
- int getCount(): 返回適配器中數(shù)據(jù)集的總數(shù)。
- Object getItem(int position): 獲取與數(shù)據(jù)集中指定位置關(guān)聯(lián)的數(shù)據(jù)項(xiàng)。
- long getItemId(int position): 獲取與列表中指定位置關(guān)聯(lián)的行 ID。
- int getItemViewType(int position): 獲取將由 getView(int, View, ViewGroup) 方法指定項(xiàng)目創(chuàng)建的視圖類型。
- View getView(int position, View convertView, ViewGroup parent): 獲取顯示數(shù)據(jù)集中指定位置的數(shù)據(jù)的視圖。
- int getViewTypeCount(): 返回將由其創(chuàng)建的視圖類型的數(shù)量 getView(int, View, ViewGroup)。
- boolean hasStableIds(): 項(xiàng)目 ID 在基礎(chǔ)數(shù)據(jù)更改期間是否穩(wěn)定。
- boolean isEmpty(): 是否為空。
- void registerDataSetObserver(DataSetObserver observer): 注冊一個在此適配器使用的數(shù)據(jù)發(fā)生更改時調(diào)用的觀察者。
- unregisterDataSetObserver(DataSetObserver observer): 取消注冊先前已通過此適配器注冊的觀察者? registerDataSetObserver(DataSetObserver)。
這些方法簡要地描述了 Adapter 接口的功能,主要是用于獲取數(shù)據(jù)項(xiàng)的數(shù)量、獲取數(shù)據(jù)項(xiàng)本身以及與視圖相關(guān)的操作。通過實(shí)現(xiàn)這些方法,可以創(chuàng)建自定義的適配器以滿足特定的數(shù)據(jù)顯示需求。
SpinnerAdapter
SpinnerAdapter 是用于在 Spinner(下拉框)中顯示數(shù)據(jù)的接口。與其他 Adapter 不同的是,SpinnerAdapter 專門用于 Spinner 控件,因此只有一個公開方法:
- View getDropDownView(int position, View convertView, ViewGroup parent): 根據(jù)下拉式彈出窗口中顯示數(shù)據(jù)集中指定的位置獲取數(shù)據(jù)的視圖。
這個方法與 getView() 方法類似,但它專門用于在 Spinner 的下拉列表中顯示數(shù)據(jù)項(xiàng)的視圖。通常情況下,你會根據(jù) position 參數(shù)來獲取對應(yīng)位置的數(shù)據(jù)項(xiàng),并將其顯示在一個視圖中返回。需要注意的是,Spinner 在展開時會顯示一個下拉列表,而這個方法返回的視圖就是用于在下拉列表中顯示的每個數(shù)據(jù)項(xiàng)的樣式。
ListAdapter
ListAdapter 是用于在 ListView 中顯示數(shù)據(jù)的接口,它有兩個方法:
- boolean areAllItemsEnabled(): 設(shè)置是否啟用此適配器中的所有項(xiàng)目。如果所有的項(xiàng)目都是可用的,則返回 true;否則返回 false。當(dāng)列表中的所有項(xiàng)都是可點(diǎn)擊的時候,這個方法通常返回 true。
- boolean isEnabled(int position): 判斷指定位置上的項(xiàng)目是否啟用。通常情況下,這個方法會根據(jù)列表中的每個項(xiàng)的狀態(tài)來決定其是否可點(diǎn)擊。如果指定位置上的項(xiàng)目是可用的(可以點(diǎn)擊的),則返回 true;否則返回 false。
這兩個方法主要用于控制 ListView 中每個項(xiàng)的可點(diǎn)擊狀態(tài)。
BaseAdapter
BaseAdapter 是 Android 中的一個抽象類,用于實(shí)現(xiàn)基本的適配器功能,通常用于在界面和數(shù)據(jù)之間進(jìn)行數(shù)據(jù)綁定。
下面是對這些方法的簡要說明:
- boolean areAllItemsEnabled(): 判斷是否啟用了適配器中的所有項(xiàng)目。
- CharSequence[] getAutofillOptions(): 獲取可幫助 AutofillService 自動填充支持的視圖的適配器數(shù)據(jù)的字符串表示形式。
- View getDropDownView(int position, View convertView, ViewGroup parent): 根據(jù)下拉式彈出窗口中顯示的數(shù)據(jù)集中指定的位置獲取數(shù)據(jù)的視圖。
- int getItemViewType(int position): 獲取由 getView(int, View, ViewGroup) 方法指定的項(xiàng)目創(chuàng)建的視圖類型。
- View getView(int position, View convertView, ViewGroup parent): 獲取顯示在數(shù)據(jù)集中指定位置的數(shù)據(jù)的視圖。
- boolean hasStableIds(): 在基礎(chǔ)數(shù)據(jù)更改期間判斷項(xiàng)目 id 是否穩(wěn)定。
- boolean isEmpty(): 判斷適配器是否為空。
- boolean isEnabled(int position): 判斷指定位置上的項(xiàng)目是否啟用。
- void notifyDataSetChanged(): 通知附屬的觀察者,底層數(shù)據(jù)已被更改,任何反映數(shù)據(jù)集的視圖都應(yīng)該自行刷新。
- void notifyDataSetInvalidated(): 通知所附的觀察員,底層數(shù)據(jù)不再有效或可用。
- void setAutofillOptions(CharSequence... options): 設(shè)置返回的值是由 getAutofillOptions() 方法返回的選項(xiàng)。
- void registerDataSetObserver(DataSetObserver observer): 注冊一個觀察者,在適配器使用的數(shù)據(jù)發(fā)生更改時調(diào)用。
- void unregisterDataSetObserver(DataSetObserver observer): 取消注冊之前已經(jīng)通過 registerDataSetObserver(DataSetObserver) 方法注冊的觀察者。
方法說明簡單明了,主要就是獲取數(shù)據(jù)項(xiàng)的數(shù)量和獲取數(shù)據(jù)項(xiàng),獲取數(shù)據(jù)項(xiàng)的類型和視圖。
現(xiàn)在我們看看我們要重寫哪些方法
-
首先和監(jiān)聽器相關(guān)的都不用重寫,因?yàn)闀簳r用不著,于是去掉
- notifyDataSetChanged()
- notifyDataSetInvalidated()
- registerDataSetObserver(DataSetObserver observer)
- registerDataSetObserver(DataSetObserver observer)
-
跟?自動填充?相關(guān)的也暫時用不著 (以后有機(jī)會介紹吧),于是去掉
- setAutofillOptions(CharSequence... options)
- getAutofillOptions()
-
有些方法可以有選擇性的實(shí)現(xiàn)
- getDropDownView()
- areAllItemsEnabled()
- isEnabled()
- isEmpty()
- getItemViewType()
- getItemViewTypeCount()
好了,還剩下 4 個方法:
- getView(int position, View convertView, ViewGroup parent): 這是一個最重要的方法,用于獲取顯示在數(shù)據(jù)集中指定位置的數(shù)據(jù)的視圖。在這個方法中,你需要創(chuàng)建或者重用視圖,并將數(shù)據(jù)綁定到視圖上。
- int getCount(): 這個方法返回數(shù)據(jù)集中的項(xiàng)目數(shù)量。在適配器中,你需要實(shí)現(xiàn)這個方法以提供數(shù)據(jù)集中項(xiàng)目的數(shù)量。
- Object getItem(int position): 這個方法用于獲取與數(shù)據(jù)集中指定位置關(guān)聯(lián)的數(shù)據(jù)項(xiàng)。通常,你可以根據(jù)位置返回數(shù)據(jù)集中相應(yīng)位置的對象。
- long getItemId(int position): 這個方法用于獲取與列表中指定位置關(guān)聯(lián)的行 ID。一般來說,可以返回與該位置相關(guān)的數(shù)據(jù)項(xiàng)的唯一標(biāo)識符,如果沒有可以返回該位置。
這些方法是一個基本適配器必須實(shí)現(xiàn)的核心方法,它們用于將數(shù)據(jù)與視圖進(jìn)行綁定并確定數(shù)據(jù)的特征。
自定義 BaseAdapter
<?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="match_parent"android:orientation="vertical"android:gravity="center"><ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>
package com.example.myapplication;import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 準(zhǔn)備數(shù)據(jù)List<String> dataList = new ArrayList<>();dataList.add("項(xiàng)目 1:Java");dataList.add("項(xiàng)目 2:C#");dataList.add("項(xiàng)目 3:Python");dataList.add("項(xiàng)目 4:C++");dataList.add("項(xiàng)目 5:PHP");// 找到ListViewListView listView = findViewById(R.id.listView);// 創(chuàng)建適配器CustomAdapter adapter = new CustomAdapter(this, dataList);// 設(shè)置適配器listView.setAdapter(adapter);}// 自定義 BaseAdapterprivate static class CustomAdapter extends BaseAdapter {private List<String> mData;private LayoutInflater mInflater;// 構(gòu)造函數(shù)public CustomAdapter(Context context, List<String> data) {mData = data;mInflater = LayoutInflater.from(context);}// 返回數(shù)據(jù)集的大小@Overridepublic int getCount() {return mData.size();}// 返回指定位置的數(shù)據(jù)項(xiàng)@Overridepublic String getItem(int position) {return mData.get(position);}// 返回指定位置的行ID@Overridepublic long getItemId(int position) {// 對于簡單情況,我們返回位置作為IDreturn position;}// 返回指定位置的視圖@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);holder = new ViewHolder();holder.textView = convertView.findViewById(android.R.id.text1);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 獲取數(shù)據(jù)項(xiàng)并設(shè)置到TextView中String item = getItem(position);holder.textView.setText(item);return convertView;}// ViewHolder類,用于優(yōu)化列表項(xiàng)的視圖static class ViewHolder {TextView textView;}}
}
在這個示例中,我們創(chuàng)建了一個自定義的 CustomAdapter 類,繼承自 BaseAdapter,并實(shí)現(xiàn)了其中的四個核心方法:getCount()、getItem()、getItemId() 和 getView()。同時,在 MainActivity 中,我們實(shí)例化了 CustomAdapter 并將其設(shè)置給了 ListView。?
?運(yùn)行結(jié)果:
參考文檔
- Android 官方 BaseAdapter
Android ListView 列表控件
關(guān)于 ListView ,其實(shí) Android Adapter 適配器 和 Android 自定義 Adapter 都有已經(jīng)使用過好幾次了,我們這里就不再講解基本的使用了。
ListView 的屬性和方法
ListView 的常用屬性:
- android:footerDividersEnabled: 是否在 footerView(表尾)前繪制一個分隔條,默認(rèn)為 true。
- android:headerDividersEnabled: 是否在 headerView(表頭)前繪制一個分隔條,默認(rèn)為 true。
- android:divider: 設(shè)置分隔條,可以用顏色分割,也可以用 drawable 資源分割。
- android:dividerHeight: 設(shè)置分隔條的高度。
- android:entries: ListView 要顯示的數(shù)據(jù)資源,在 Android Adapter 適配器中我們有用到過。
這些屬性可以用來定制 ListView 的外觀和分隔線的顯示。
至于方法,ListView 提供了很多與表頭表尾分隔線相關(guān)的方法,但是我們在日常開發(fā)中常用的方法并不太多,通常使用的方法包括 setAdapter() 用于設(shè)置適配器,以及一些用于監(jiān)聽事件的方法,比如 setOnItemClickListener() 用于設(shè)置列表項(xiàng)的點(diǎn)擊事件監(jiān)聽器。
表頭表尾分割線的設(shè)置
ListView 沒有直接設(shè)置表頭和表尾的屬性,但是你可以通過編程的方式在 Java 代碼中設(shè)置表頭和表尾。方法 addHeaderView(View v) 和 addFooterView(View v) 就是用來實(shí)現(xiàn)這個目的的。
這些方法允許你在 ListView 中添加表頭和表尾的視圖,其中 addHeaderView(View v) 方法用于添加表頭,而 addFooterView(View v) 方法用于添加表尾。你可以傳入一個自定義的 View 對象作為表頭或表尾的內(nèi)容。
此外,如果需要進(jìn)一步控制表頭或表尾的交互,可以使用重載的方法 addHeaderView(View v, Object data, boolean isSelectable) 和 addFooterView(View v, Object data, boolean isSelectable),其中 isSelectable 參數(shù)用于指定表頭或表尾是否可以被選中。
記住,如果你使用了 addHeaderView() 方法,你必須在調(diào)用 setAdapter() 方法之前添加表頭,否則會出現(xiàn)錯誤。這是因?yàn)樘砑颖眍^必須在設(shè)置適配器之前完成。
例子:
<?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="match_parent"android:orientation="vertical"android:gravity="center"><ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>
package com.example.myapplication;import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 準(zhǔn)備數(shù)據(jù)List<String> dataList = new ArrayList<>();dataList.add("項(xiàng)目 1:Java");dataList.add("項(xiàng)目 2:C#");dataList.add("項(xiàng)目 3:Python");dataList.add("項(xiàng)目 4:C++");dataList.add("項(xiàng)目 5:PHP");// 找到ListViewListView listView = findViewById(R.id.listView);// 創(chuàng)建適配器ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataList);// 添加表頭// 注意:addHeaderView() 必須在 setAdapter() 之前調(diào)用// 如果表頭不需要被選中,最后一個參數(shù)可以傳入 false// 如果需要被選中,則傳入 truelistView.addHeaderView(createHeaderView(), null, false);// 添加表尾// 同樣,addFooterView() 也必須在 setAdapter() 之前調(diào)用listView.addFooterView(createFooterView(), null, false);// 設(shè)置適配器listView.setAdapter(adapter);}// 創(chuàng)建表頭的視圖private View createHeaderView() {TextView headerView = new TextView(this);headerView.setText("表頭視圖");// 設(shè)置表頭樣式,比如背景色、文字大小等headerView.setBackgroundColor(Color.BLUE); // 設(shè)置背景色為藍(lán)色headerView.setTextColor(Color.WHITE); // 設(shè)置文字顏色為白色headerView.setTextSize(18); // 設(shè)置文字大小為 18spreturn headerView;}// 創(chuàng)建表尾的視圖private View createFooterView() {TextView footerView = new TextView(this);footerView.setText("表尾視圖");// 設(shè)置表尾樣式,比如背景色、文字大小等footerView.setBackgroundColor(Color.GREEN); // 設(shè)置背景色為綠色footerView.setTextColor(Color.WHITE); // 設(shè)置文字顏色為白色footerView.setTextSize(18); // 設(shè)置文字大小為 18spreturn footerView;}
}
列表從底部開始顯示 android:stackFromBottom
android:stackFromBottom="true" 是一個用于 ListView 的布局屬性,用于設(shè)置列表從底部開始顯示。
當(dāng)設(shè)置為 true 時,ListView 將會從底部開始顯示列表項(xiàng),即最后一個列表項(xiàng)會顯示在列表的底部,而第一個列表項(xiàng)會顯示在列表的頂部。
下面是一個示例 XML 布局文件,演示如何使用 android:stackFromBottom="true" 屬性:
<ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent"android:stackFromBottom="true" />
設(shè)置點(diǎn)擊顏色 cacheColorHint
android:cacheColorHint 是一個用于 ListView 的屬性,用于設(shè)置當(dāng)滾動或點(diǎn)擊時,背景色的緩存色。
默認(rèn)情況下,ListView 在滾動時會繪制一個緩存位圖來加速滾動的過程。而這個緩存位圖的背景色默認(rèn)是黑色。當(dāng)你將一個有背景的 ListView 放在一個有顏色的背景上時,當(dāng)你滾動 ListView 時,滾動過程中的空白部分會暴露出背景色,此時就會看到黑色背景,給人一種不連續(xù)的感覺。
通過設(shè)置 android:cacheColorHint 屬性為透明色,即 #00000000,可以解決這個問題。這樣,在滾動或點(diǎn)擊時,空白部分就會顯示成透明色,與背景融合,不會再出現(xiàn)黑色背景。
下面是一個示例 XML 布局文件,演示如何使用 android:cacheColorHint 屬性:
<ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/listview_background"android:cacheColorHint="#00000000" />
隱藏滑動條
可以通過設(shè)置 android:scrollbars 屬性為 none 來隱藏 ListView 的滾動條,也可以通過調(diào)用 setVerticalScrollBarEnabled(false) 來達(dá)到同樣的效果。
1、使用 XML 屬性 android:scrollbars="none":
<ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="none" />
2、使用 Java 代碼 setVerticalScrollBarEnabled(false):
ListView listView = findViewById(R.id.listView);
listView.setVerticalScrollBarEnabled(false);