引言
最近做的項(xiàng)目想仿做滴滴出行首頁(yè)的懸浮框俗冻。
正文
效果參考滴滴出行;
工欲善其事,必先利其器!來(lái)......
Spinner詳解
Spinner控件初始化時(shí),會(huì)調(diào)用它的選擇監(jiān)聽(tīng)事件溜徙,默認(rèn)選擇第一個(gè)
一、Spinner比較好用的屬性
-
Spinner
的entries
屬性犀填,就可以不用設(shè)置Spinner
的Adapter
蠢壹,也可以填充數(shù)據(jù)
<Spinner
android:id="@+id/spCity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="請(qǐng)選擇城市"
android:entries="@array/cities"/>
-
Spinner
的spinnerMode
屬性,Spinner
顯示為對(duì)話框
或者是下拉框
形式九巡;
android:spinnerMode=["dialog"|"dropdown"]
prompt屬性表示spinner列表上方的提示
spinnerMode="dialog"效果圖图贸,可以看到我們?cè)O(shè)置的提示符"請(qǐng)選擇城市"
spinnerMode="dropdown"效果圖
二、設(shè)置spinner顯示數(shù)據(jù)
使用Spinner
布局文件使用的是系統(tǒng)默認(rèn)的冕广;使用創(chuàng)建ArrayAdapter兩種方式疏日,傳入不同的數(shù)據(jù)源;
- 使用xml文件作為數(shù)據(jù)源
private void initView(){
city= (Spinner) findViewById(R.id.spCity);
SpinnerAdapter adapter=null;
adapter=ArrayAdapter.createFromResource(this,R.array.cities,android.R.layout.simple_spinner_dropdown_item);
city.setAdapter(adapter);
}
- 使用數(shù)組或者是List作為數(shù)據(jù)數(shù)據(jù)源
ArrayList<String> list=new ArrayList<String>();
SpinnerAdapter adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,list);
三撒汉、spinner點(diǎn)擊事件處理
city.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//這個(gè)方法里可以對(duì)點(diǎn)擊事件進(jìn)行處理
//i指的是點(diǎn)擊的位置,通過(guò)i可以取到相應(yīng)的數(shù)據(jù)源
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
})
四沟优、用代碼來(lái)點(diǎn)擊spinner
//選擇Spinner里的第二個(gè)數(shù)據(jù);
city.setSelection(1,true);
自定義Spinner
-
spinner
就是下拉選擇組件,系統(tǒng)自帶的spinner使用起來(lái)非常方便睬辐,首先定義一個(gè)array(strings.xml)净神,如下:
<array name="grade">
<item>一年級(jí)</item>
<item>二年級(jí)</item>
<item>三年級(jí)</item>
<item>四年級(jí)</item>
<item>五年級(jí)</item>
<item>六年級(jí)</item>
</array>
代碼如下:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.grade, android.R.layout.simple_spinner_item);
spinner.setAdapter(adapter);
這樣就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的spinner,顯示如下:
但這并不是我想要的樣式和效果溉委,下面我們就一點(diǎn)點(diǎn)的來(lái)改造它。
(1)改變初始布局
spinner_layout.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<TextView xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
xmlns:tools = "http://schemas.android.com/tools"
android:textColor = "#6d6d6d"
android:textSize = "15sp"
android:drawableRight = "@drawable/arrow"
android:drawablePadding = "5dp"
tools:text = "一年級(jí)" >
</TextView >
然后替換createFromResource
中的即可爱榕,如下:
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.grade, R.layout.spinner_layout);
這樣還不夠瓣喊,因?yàn)檫€有一個(gè)帶箭頭的背景,將背景設(shè)置為透明即可黔酥,如下:
spinner.setBackgroundColor(0x0);
這樣初始布局的展示就與spinner_layout一樣了藻三。
(2)改變列表item布局
經(jīng)過(guò)上面的修改后,發(fā)現(xiàn)彈窗中列表item的布局也變成了spinner_layout跪者,查看ArrayAdapter的構(gòu)造函數(shù)可知有mResource和mDropDownResource兩個(gè)變量棵帽,其中mResource就是初始布局,而mDropDownResource則是列表item的布局渣玲。
而createFromResource
函數(shù)中逗概,mResource
和mDropDownResource
賦值相同。但是ArrayAdapter
還有一個(gè)setDropDownViewResource
函數(shù)忘衍。
首先定義一個(gè)布局逾苫,如下:
spinner_layout.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:textColor="#6d6d6d"
android:textSize="15sp"
android:padding="8dp"
android:gravity="center_horizontal"
tools:text="一年級(jí)">
</TextView>
然后使用setDropDownViewResource函數(shù)即可卿城,如下:
adapter.setDropDownViewResource(R.layout.spinner_item);
(3)改變彈窗背景及位置
在開(kāi)始的動(dòng)畫(huà)中可以看到彈窗會(huì)遮擋住,我們想讓彈窗處于下方铅搓,同時(shí)彈窗是圓角帶箭頭的瑟押。
這就需要使用spinner
的兩個(gè)函數(shù)setPopupBackgroundResource
和setDropDownVerticalOffset
。
但是注意這兩個(gè)函數(shù)都需要在android4.1
版本及以上星掰,鑒于目前4.1以下版本已經(jīng)很少了多望,所以我們只考慮4.1以上即可,代碼如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
spinner.setPopupBackgroundResource(R.drawable.bg_spinner);
spinner.setDropDownVerticalOffset(dip2px(20));
}
另外有一種方式同樣也可以達(dá)到效果氢烘,在這里記錄一下:
(但是很粗糙扮匠,沒(méi)能滿足緊靠正下方的需求)
解決方案:這是因?yàn)閟pinner有一個(gè)屬性:android:overlapAnchor=”false”
肋殴。
這個(gè)屬性默認(rèn)是true。改為false即可。但是不知道為什么這個(gè)屬性在代碼提示中是沒(méi)有的钙姊。所以記錄下來(lái)。
(4)添加選中效果
經(jīng)過(guò)上面的處理醋闭,我們已經(jīng)得到想要的樣式鲤看。但是還差一點(diǎn),彈窗列表中缺少選中的樣式脓斩。比如說(shuō)我當(dāng)前選擇“二年級(jí)”木西,在彈窗中,對(duì)應(yīng)的item
字體應(yīng)該加深加粗随静。在spinner源碼中搜尋了一遍八千,發(fā)現(xiàn)并沒(méi)有對(duì)應(yīng)的函數(shù)和解決方法,那么我們自己動(dòng)手吧燎猛。
其實(shí)spinner
是使用adapter
來(lái)加載列表的恋捆,而我們使用createFromResource
函數(shù)會(huì)自動(dòng)創(chuàng)建了adapter,我們可以自定義一個(gè)adapter重绷,如下:
public class SpinnerAdapter<T> extends ArrayAdapter<T> {
private int selectedPostion;
public void setSelectedPostion(int selectedPostion) {
this.selectedPostion = selectedPostion;
}
public SpinnerAdapter(@NonNull Context context, int resource, @NonNull T[] objects) {
super(context, resource, objects);
}
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getDropDownView(position, convertView, parent);
TextView textView = (TextView) view;
if (selectedPostion == position) {
textView.setTextColor(0xff373741);
textView.getPaint().setFakeBoldText(true);
} else {
textView.setTextColor(0xff6d6d6d);
textView.getPaint().setFakeBoldText(false);
}
return view;
}
public static @NonNull
SpinnerAdapter<CharSequence> createFromResource(@NonNull Context context, @ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
final CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
return new SpinnerAdapter<>(context, textViewResId, strings);
}
}
注意ArrayAdapter
中的getDropDownView
函數(shù)是獲取彈窗item
使用的view
的沸停,而不是getView
函數(shù)。
同時(shí)我們要重新寫(xiě)一個(gè)createFromResource
函數(shù)昭卓。
將之前使用的adapter
替換成自定義這個(gè)愤钾,同時(shí)為spinner
設(shè)置監(jiān)聽(tīng)即可,更改后的完整代碼如下:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
adapter = SpinnerAdapter.createFromResource(this,R.array.grade,R.layout.spinner_layout);
adapter.setDropDownViewResource(R.layout.spinner_item);
spinner.setBackgroundColor(0x0);
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.JELLY_BEAN){
spinner.setPopupBackgroundResource(R.drawable.bg_spinner);
spinner.setDropDownVerticalOffset(dip2px(20));
}
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
@Override
public void onItemSelected (AdapterView < ? > parent, View view,int position,long id){
adapter.setSelectedPostion(position);
}
@Override
public void onNothingSelected (AdapterView < ? > parent){
}
});