重拾Android之路之Spinner

引言

最近做的項(xiàng)目想仿做滴滴出行首頁(yè)的懸浮框俗冻。

正文

效果參考滴滴出行;

工欲善其事,必先利其器!來(lái)......

Spinner詳解

Spinner控件初始化時(shí),會(huì)調(diào)用它的選擇監(jiān)聽(tīng)事件溜徙,默認(rèn)選擇第一個(gè)

一、Spinner比較好用的屬性
  1. Spinnerentries屬性犀填,就可以不用設(shè)置SpinnerAdapter蠢壹,也可以填充數(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"/>
  1. SpinnerspinnerMode屬性,Spinner顯示為對(duì)話框或者是下拉框形式九巡;
android:spinnerMode=["dialog"|"dropdown"]
prompt屬性表示spinner列表上方的提示

spinnerMode="dialog"效果圖图贸,可以看到我們?cè)O(shè)置的提示符"請(qǐng)選擇城市"

spinnerMode="dropdown"效果圖

spinner_drop_item
二、設(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ù)中逗概,mResourcemDropDownResource賦值相同。但是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ù)setPopupBackgroundResourcesetDropDownVerticalOffset

但是注意這兩個(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){
    }
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末候醒,一起剝皮案震驚了整個(gè)濱河市能颁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倒淫,老刑警劉巖伙菊,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡占业,警方通過(guò)查閱死者的電腦和手機(jī)绒怨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谦疾,“玉大人南蹂,你說(shuō)我怎么就攤上這事∧罨校” “怎么了六剥?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)峰伙。 經(jīng)常有香客問(wèn)我疗疟,道長(zhǎng),這世上最難降的妖魔是什么瞳氓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任策彤,我火速辦了婚禮,結(jié)果婚禮上匣摘,老公的妹妹穿的比我還像新娘店诗。我一直安慰自己,他們只是感情好音榜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布庞瘸。 她就那樣靜靜地躺著,像睡著了一般赠叼。 火紅的嫁衣襯著肌膚如雪擦囊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天嘴办,我揣著相機(jī)與錄音瞬场,去河邊找鬼。 笑死涧郊,一個(gè)胖子當(dāng)著我的面吹牛泌类,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播底燎,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弹砚!你這毒婦竟也來(lái)了双仍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤桌吃,失蹤者是張志新(化名)和其女友劉穎朱沃,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逗物,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年搬卒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翎卓。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡契邀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出失暴,到底是詐尸還是另有隱情坯门,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布逗扒,位于F島的核電站古戴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矩肩。R本人自食惡果不足惜现恼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍檩。 院中可真熱鬧叉袍,春花似錦、人聲如沸建炫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肛跌。三九已至艺配,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衍慎,已是汗流浹背转唉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稳捆,地道東北人赠法。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乔夯,于是被迫代替她去往敵國(guó)和親砖织。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容