android提供的spinner可能会因为项目的需求而不能使用,这时候我们往往会自己定义一个。最近在做的项目遇到了这种情况,自己用popuwindow定义了一个下拉框的样式,记录下来留着以后参考~先上效果图~
点击头部右边的按钮,弹出长度与上方的控件长度一致的下拉框。
下面来说说是如何实现的。定义出第一个图片的布局和弹出框(一个listview)的布局,程序的源码里面有,这里就不在多说了~listview需要自己定义一个myspinneradapter~做好这些准备之后,就是弹出框的实现了~
查看源代码
<code>1</code>
<code>@override</code>
<code>2</code>
<code> </code><code>protected</code><code>void</code><code>oncreate(bundle savedinstancestate) {</code>
<code>3</code>
<code> </code><code>super</code><code>.oncreate(savedinstancestate);</code>
<code>4</code>
<code> </code><code>setcontentview(r.layout.activity_main);</code>
<code>5</code>
<code> </code><code>textview = (textview) findviewbyid(r.id.text);</code>
<code>6</code>
<code> </code><code>imgview = findviewbyid(r.id.arrowbut);</code>
<code>7</code>
<code> </code><code>// 实例化一个list,添加数据</code>
<code>8</code>
<code> </code><code>list =</code><code>new</code><code>arraylist<string>();</code>
<code>9</code>
<code> </code><code>list.add(</code><code>"第一展厅"</code><code>);</code>
<code>10</code>
<code> </code><code>list.add(</code><code>"第二展厅"</code><code>);</code>
<code>11</code>
<code> </code><code>list.add(</code><code>"第三展厅"</code><code>);</code>
<code>12</code>
<code> </code><code>// 实例化一个适配器,list的数据作为adapter的数据</code>
<code>13</code>
<code> </code><code>adapter =</code><code>new</code><code>myspinneradapter(</code><code>this</code><code>, list);</code>
<code>14</code>
<code> </code><code>// 默认设置下拉框的标题为数据的第一个</code>
<code>15</code>
<code> </code><code>textview.settext((charsequence) adapter.getitem(</code><code>0</code><code>));</code>
<code>16</code>
<code> </code><code>spinnerlayout = (linearlayout) findviewbyid(r.id.spinnerid);</code>
<code>17</code>
<code> </code><code>// 点击右侧按钮,弹出下拉框</code>
<code>18</code>
<code> </code><code>imgview.setonclicklistener(</code><code>new</code><code>onclicklistener() {</code>
<code>19</code>
<code>20</code>
<code> </code><code>@override</code>
<code>21</code>
<code> </code><code>public</code><code>void</code><code>onclick(view v) {</code>
<code>22</code>
<code>23</code>
<code> </code><code>showwindow(v);</code>
<code>24</code>
<code>25</code>
<code> </code><code>}</code>
<code>26</code>
<code> </code><code>});</code>
<code>27</code>
<code> </code><code>}</code>
<code>28</code>
<code>29</code>
<code> </code><code>@suppresswarnings</code><code>(</code><code>"deprecation"</code><code>)</code>
<code>30</code>
<code> </code><code>public</code><code>void</code><code>showwindow(view v) {</code>
<code>31</code>
<code> </code><code>// 找到布局文件</code>
<code>32</code>
<code> </code><code>layout = (linearlayout) layoutinflater.from(</code><code>this</code><code>).inflate(r.layout.mypinner_dropdown,</code><code>null</code><code>);</code>
<code>33</code>
<code> </code><code>// 实例化listview</code>
<code>34</code>
<code> </code><code>listview = (listview) layout.findviewbyid(r.id.listview);</code>
<code>35</code>
<code> </code><code>// 设置listview的适配器</code>
<code>36</code>
<code> </code><code>listview.setadapter(adapter);</code>
<code>37</code>
<code> </code><code>// 实例化一个popuwindow对象</code>
<code>38</code>
<code> </code><code>popupwindow =</code><code>new</code><code>popupwindow(v);</code>
<code>39</code>
<code> </code><code>// 设置弹框的宽度为布局文件的宽</code>
<code>40</code>
<code> </code><code>popupwindow.setwidth(spinnerlayout.getwidth());</code>
<code>41</code>
<code> </code><code>// 高度随着内容变化</code>
<code>42</code>
<code> </code><code>popupwindow.setheight(layoutparams.wrap_content);</code>
<code>43</code>
<code> </code><code>// 设置一个透明的背景,不然无法实现点击弹框外,弹框消失</code>
<code>44</code>
<code> </code><code>popupwindow.setbackgrounddrawable(</code><code>new</code><code>bitmapdrawable());</code>
<code>45</code>
<code> </code><code>// 设置点击弹框外部,弹框消失</code>
<code>46</code>
<code> </code><code>popupwindow.setoutsidetouchable(</code><code>true</code><code>);</code>
<code>47</code>
<code> </code><code>// 设置焦点</code>
<code>48</code>
<code> </code><code>popupwindow.setfocusable(</code><code>true</code><code>);</code>
<code>49</code>
<code> </code><code>// 设置所在布局</code>
<code>50</code>
<code> </code><code>popupwindow.setcontentview(layout);</code>
<code>51</code>
<code> </code><code>// 设置弹框出现的位置,在v的正下方横轴偏移textview的宽度,为了对齐~纵轴不偏移</code>
<code>52</code>
<code> </code><code>popupwindow.showasdropdown(v, -textview.getwidth(),</code><code>0</code><code>);</code>
<code>53</code>
<code> </code><code>// listview的item点击事件</code>
<code>54</code>
<code> </code><code>listview.setonitemclicklistener(</code><code>new</code><code>onitemclicklistener() {</code>
<code>55</code>
<code>56</code>
<code>57</code>
<code> </code><code>public</code><code>void</code><code>onitemclick(adapterview<?> arg0, view arg1,</code><code>int</code><code>arg2,</code><code>long</code> <code>arg3) {</code>
<code>58</code>
<code> </code><code>// todo auto-generated method stub</code>
<code>59</code>
<code> </code><code>textview.settext(list.get(arg2));</code><code>// 设置所选的item作为下拉框的标题</code>
<code>60</code>
<code> </code><code>// 弹框消失</code>
<code>61</code>
<code> </code><code>popupwindow.dismiss();</code>
<code>62</code>
<code> </code><code>popupwindow =</code><code>null</code><code>;</code>
<code>63</code>
<code>64</code>
<code>65</code>
<code>66</code>
注释已经写得很清楚了,这里就不再多说了~
源码:
<code>https://github.com/liangjie0521/testspinner2.git</code>
有时候因为项目的界面风格 很多控件如果使用原生的样式感觉会与整体风格有些不搭 所以需要自定义样式 很多项目中自定义控件都是必不可少的 这里参考网上的一些资料 实现了一个自定义spinner 记录下 加深印象
效果图:
弹框是通过一个重写的dialog和listview实现
第一步 重写dialog类selectdialog.java
[java]
view plaincopyprint?
import android.app.alertdialog;
import android.content.context;
import android.os.bundle;
public class selectdialog extends alertdialog {
public selectdialog(context context, int theme) {
super(context, theme);
}
public selectdialog(context context) {
super(context);
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
// setcontentview(r.layout.slt_cnt_type);
}
第二步重写spinner类customerspinner.java
import java.util.arraylist;
import android.util.attributeset;
import android.view.layoutinflater;
import android.view.view;
import android.widget.adapterview;
import android.widget.listview;
import android.widget.spinner;
import android.widget.adapterview.onitemclicklistener;
public class customerspinner extends spinner implements onitemclicklistener {
public static selectdialog dialog = null;
private arraylist<string> list;
public static string text;
public customerspinner(context context, attributeset attrs) {
super(context, attrs);
//如果视图定义了onclicklistener监听器,调用此方法来执行
public boolean performclick() {
context context = getcontext();
final layoutinflater inflater = layoutinflater.from(getcontext());
final view view = inflater.inflate(r.layout.formcustomspinner, null);
final listview listview = (listview) view
.findviewbyid(r.id.formcustomspinner_list);
listviewadapter adapters = new listviewadapter(context, getlist());
listview.setadapter(adapters);
listview.setonitemclicklistener(this);
dialog = new selectdialog(context, r.style.dialog);//创建dialog并设置样式主题
layoutparams params = new layoutparams(650, layoutparams.fill_parent);
dialog.setcanceledontouchoutside(true);// 设置点击dialog外部任意区域关闭dialog
dialog.show();
dialog.addcontentview(view, params);
return true;
public void onitemclick(adapterview<?> view, view itemview, int position,
long id) {
setselection(position);
settext(list.get(position));
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
public arraylist<string> getlist() {
return list;
public void setlist(arraylist<string> list) {
this.list = list;
public string gettext() {
return text;
public void settext(string text) {
this.text = text;
这里用listview来显示数据 arraylist<string> list存储所要显示的数据 text存储每次spinner选中的值 在监听spinner并获取当前选中的值的时候用到
dialog的样式设置:styles.xml
[html]
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="dialog" parent="@android:style/theme.dialog">
<item name="android:windowframe">@null</item><!--边框-->
<item name="android:windowisfloating">true</item><!--是否浮现在activity之上-->
<item name="android:windowistranslucent">false</item><!--半透明-->
<item name="android:windownotitle">true</item><!--无标题-->
<!-- <item name="android:windowbackground">@color/alpha_bg</item>背景透明-->
<item name="android:backgrounddimenabled">false</item><!--模糊-->
</style>
</resources>
listview的代码很简单 自己写一个adapter就好了
第三步 在xml文件中引用自定义的spinner
main.xml
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="#ffffff" android:id="@+id/layout"
>
<textview android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="草帽海贼团 :" android:textcolor="#000000" android:textsize="20dp"
android:layout_margintop="15dp"/>
<com.spinner.test.customerspinner android:background="@drawable/bg_spinner"
android:layout_width="150dp" android:layout_height="50dp" android:id="@+id/spinner"
android:layout_margintop="15dp"/>
</linearlayout>
到这里差不多就完成了 不过这个还有个缺陷 每次使用时通过 spinner.setlist(list);为其加载数据 当程序返回或者退出这个节目在进入时 listview中的数据会重复 这里只能通过这个办法来解决了
@override
public boolean onkeydown(int keycode, keyevent event) {
if(keycode == keyevent.keycode_back){
list.clear();
return super.onkeydown(keycode, event);
每次返回或退出时 清空list 就可以啦
下载地址:http://download.csdn.net/download/wanglj0925/4634852
spinner是常用控件之一,属于adapterview的一种,应用时需要 通过adapter 将数据和view视图联系起来,并且有各种事件回调函数,较为方便。
但发现一个问题,spinner控件,很难控制其外观与显示大小,在同一个布局中,很难与其它控件外观协调起来。最后用button控件模仿spinner的效果,应用起来也较为方便。
应用button时,需要图片配合button的各种切换状态,点击时弹出对话框,实现列表选择即可。
需要写一个selector文件,在button状态变化时,切换背景图,在button的onclick事件函数中,弹出选择列表对话框
大小: 21 kb
button.rar (77.7 kb)
下载次数: 542
查看图片附件