模仿Android4.0的Spinner Button写的一个MySpinnerButton。这样在1.6~4.0.4版本都可以实现这种下拉框的效果了。

实现效果:点击屏幕上的Spinner Button,在按钮的下方会滑出一个下拉列表,滑动选择下拉列表中其中一个选项,则下拉列表收回,按钮上的文字显示为选项的内容。点击返回键或下拉列表外部区域,下拉列表收回。反复点击按钮,下拉列表反复执行滑出和收回动作。

运行图:

  

实现原理:使用PopupWindow和Button相关联(showAsDropDown)。在PopupWindow上放ListView。于是就有了下拉框的效果。

以下是代码:

入口_04MySpinnerDemo2Activity:

public class _04MySpinnerDemo2Activity extends Activity {

private MySpinnerButton mSpinnerBtn;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

this.mSpinnerBtn = (MySpinnerButton) this.findViewById(R.id.spinner_btn);
}
}

布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top|center_horizontal"
android:orientation="vertical" >

<com.haozi.demo.myspinner2.wiget.MySpinnerButton
android:id="@+id/spinner_btn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="spinner button"
/>

</LinearLayout>

封装好的MySpinnerButton:

/**
* 我的SpinnerButton
* @author haozi
*
*/
public class MySpinnerButton extends Button {

private Context context;

public MySpinnerButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
// 设置监听事件
setOnClickListener(new MySpinnerButtonOnClickListener());
}

public MySpinnerButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
// 设置监听事件
setOnClickListener(new MySpinnerButtonOnClickListener());
}

public MySpinnerButton(Context context) {
super(context);
this.context = context;
// 设置监听事件
setOnClickListener(new MySpinnerButtonOnClickListener());
}

/**
* MySpinnerButton的点击事件
* @author haozi
*
*/
class MySpinnerButtonOnClickListener implements View.OnClickListener{

@Override
public void onClick(View v) {

final MySpinnerDropDownItems mSpinnerDropDrownItems = new MySpinnerDropDownItems(context);
if (!mSpinnerDropDrownItems.isShowing()) {
mSpinnerDropDrownItems.showAsDropDown(MySpinnerButton.this);
}
}
}

/**
* MySpinnerButton的下拉列表
* @author haozi
*
*/
class MySpinnerDropDownItems extends PopupWindow{

private Context context;
private LinearLayout mLayout; // 下拉列表的布局
private ListView mListView; // 下拉列表控件
private ArrayList<HashMap<String, String>> mData;

public MySpinnerDropDownItems(Context context){
super(context);

this.context = context;
// 下拉列表的布局
mLayout = new LinearLayout(context);
mLayout.setOrientation(LinearLayout.VERTICAL);
// 下拉列表控件
mListView = new ListView(context);
mListView.setLayoutParams(new LayoutParams(MySpinnerButton.this.getLayoutParams().width, LayoutParams.WRAP_CONTENT));
mListView.setCacheColorHint(Color.TRANSPARENT);
mData = new ArrayList<HashMap<String,String>>();
for(int i=0; i<50; i++){
HashMap<String, String> mHashmap = new HashMap<String, String>();
mHashmap.put("spinner_dropdown_item_textview", "textView " + i);
mData.add(mHashmap);
}
// 为listView设置适配器
mListView.setAdapter(new MyAdapter(context,
mData, R.layout.spinner_dropdown_item,
new String[]{"spinner_dropdown_item_textview"}, new int[]{R.id.spinner_dropdown_item_textview}));
// 设置listView的点击事件
mListView.setOnItemClickListener(new MyListViewOnItemClickedListener());
// 把下拉列表添加到layout中。
mLayout.addView(mListView);

setWidth(LayoutParams.WRAP_CONTENT);
setHeight(LayoutParams.WRAP_CONTENT);
setContentView(mLayout);
setFocusable(true);

mLayout.setFocusableInTouchMode(true);
}

/**
* 我的适配器
* @author haozi
*
*/
public class MyAdapter extends BaseAdapter {

private Context context;
private List<? extends Map<String, ?>> mData;
private int mResource;
private String[] mFrom;
private int[] mTo;
private LayoutInflater mLayoutInflater;

/**
* 我的适配器的构造方法
* @param context 调用方的上下文
* @param data 数据
* @param resource
* @param from
* @param to
*/
public MyAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to){

this.context = context;
this.mData = data;
this.mResource = resource;
this.mFrom = from;
this.mTo = to;
this.mLayoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
}

/**
* 系统在绘制ListView之前,将会先调用getCount方法来获取Item的个数
*/
public int getCount() {

return this.mData.size();
}

public Object getItem(int position) {

return this.mData.get(position);
}

public long getItemId(int position) {

return position;
}

/**
* 每绘制一个 Item就会调用一次getView方法,
* 在此方法内就可以引用事先定义好的xml来确定显示的效果并返回一个View对象作为一个Item显示出来。
* 也 正是在这个过程中完成了适配器的主要转换功能,把数据和资源以开发者想要的效果显示出来。
* 也正是getView的重复调用,使得ListView的使用更 为简单和灵活。
* 这两个方法是自定ListView显示效果中最为重要的,同时只要重写好了就两个方法,ListView就能完全按开发者的要求显示。
* 而 getItem和getItemId方法将会在调用ListView的响应方法的时候被调用到。
* 所以要保证ListView的各个方法有效的话,这两个方法也得重写。
*/
public View getView(int position, View contentView, ViewGroup parent) {

contentView = this.mLayoutInflater.inflate(this.mResource, parent, false);

// 设置contentView的内容和样式,这里重点是设置contentView中文字的大小
for(int index=0; index<this.mTo.length; index++){
TextView textView = (TextView) contentView.findViewById(this.mTo[index]);
textView.setText(this.mData.get(position).get(this.mFrom[index]).toString());
}

return contentView;
}
}

/**
* listView的点击事件
* @author haozi
*
*/
class MyListViewOnItemClickedListener implements AdapterView.OnItemClickListener{

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {

TextView mTextView = (TextView) view.findViewById(R.id.spinner_dropdown_item_textview);
String content = mTextView.getText().toString();
MySpinnerButton.this.setText(content);
MySpinnerDropDownItems.this.dismiss();
}
}
}
}

下拉列表item的布局文件spinner_dropdown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/list_selector_background"
android:orientation="vertical" >

<TextView android:id="@+id/spinner_dropdown_item_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left|bottom"
android:paddingTop="11dip"
android:paddingBottom="11dip"
android:paddingLeft="5dip"
/>
</LinearLayout>

Android 自定义 SpinnerButton(转)的更多相关文章

  1. android 自定义动画

    android自定义动画注意是继承Animation,重写里面的initialize和applyTransformation,在initialize方法做一些初始化的工作,在applyTransfor ...

  2. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  3. Android自定义View4——统计图View

    1.介绍 周末在逛慕课网的时候,看到了一张学习计划报告图,详细记录了自己一周的学习情况,天天都是0节课啊!正好在学习Android自定义View,于是就想着自己去写了一个,这里先给出一张慕课网的图,和 ...

  4. (转)[原] Android 自定义View 密码框 例子

    遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...

  5. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  6. Android 自定义View (五)——实践

    前言: 前面已经介绍了<Android 自定义 view(四)-- onMeasure 方法理解>,那么这次我们就来小实践下吧 任务: 公司现有两个任务需要我完成 (1)监测液化天然气液压 ...

  7. Android 自定义 view(四)—— onMeasure 方法理解

    前言: 前面我们已经学过<Android 自定义 view(三)-- onDraw 方法理解>,那么接下我们还需要继续去理解自定义view里面的onMeasure 方法 推荐文章: htt ...

  8. Android 自定义 view(三)—— onDraw 方法理解

    前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...

  9. Android 自定义view(二) —— attr 使用

    前言: attr 在前一篇文章<Android 自定义view -- attr理解>已经简单的进行了介绍和创建,那么这篇文章就来一步步说说attr的简单使用吧 自定义view简单实现步骤 ...

随机推荐

  1. java学习第21天(IO流的使用)

    IO流分类: A:流向 输入流 读取数据 输出流 写出数据 B:数据类型 字节流 字节输入流 字节输出流 字符流 字符输入流 字符输出流 注意: a:如果我们没有明确说明按照什么分,默认按照数据类型分 ...

  2. vbs和qtp一些脚本

    ********************************************************************************************** 用vbs调 ...

  3. Linux下tar bz gz等压缩包的压缩和解压

    Linux下用户经常需要备份计算机系统中的数据,为了节省存储空间,常常将备份文件进行压缩,本文是对压缩和解压命令的大致总结 .tar.gz  解压:tar zxvf FileName.tar.gz  ...

  4. OutputDebugString输出调试信息到debugtrack

    OutPutDebugString()函数的输出则可以用DebugView捕获(DebugView也可以捕获TRACE宏的输出)eg: OutPutDebugString("输出第一调试信息 ...

  5. javascript模板引擎template.render使用

    <script type="text/javascript"> function test(){ //你的方法 } </script> 如上代码:通常我们见 ...

  6. Chapter 2 Open Book——2

    It was worse because I was tired; 更糟糕的是因为我疲惫了. I still couldn't sleep with the wind echoing around t ...

  7. EDD-SPT综合规则

    关于生产运作的计算题· 很急 谢谢·有7项任务需经某设备加工,各任务资料如下.要求:(1)试用EDD-SPT综合规则确定加工顺序(2)分别计算两种规则下的平均流程时间. 任务 J1 J2 J3 J4 ...

  8. hdu_5727_Necklace(二分匹配)

    题目连接:hdu_5727_Necklace 题意: 有2*n个珠子,n个阳珠子,n个阴珠子,现在要将这2n个珠子做成一个项链,珠子只能阴阳交替排,有些阳珠子周围如果放了指定的阴珠子就会变坏,给你一个 ...

  9. shell之路【第四篇】输入输出重定向

    输出重定向 命令输出重定向的语法为: command > file 或 command >> file 这样,输出到显示器的内容就可以被重定向到文件.果不希望文件内容被覆盖,可以使用 ...

  10. Linux常用Shell脚本珍藏【转载】

    我们在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运维常用的脚本.如何学好脚本,最关键的 ...