Android 下拉列表也是一个比较常用的控件,但是Android自带的下拉框样式效果较差,没办法,只好自己来自定义一个。其实主要是利用弹窗来实现的,看一下效果图先~~

我这边仅仅是实现简单的自定义控件,简单易懂,布局上有需要其他效果如边框、虚线等可自行加上。下拉列表是List,所以item也是可以根据需要进行内容上的丰富,修改适配器便可以。

好了,进入正题。首先,我们先创建一个标题及箭头布局,目的是用于点击后弹出下拉菜单。,代码如下所示:

接下来,创建下拉列表ListView布局,代码如下:
创建ListView,自然也要对应创建其Item的布局,代码如下:
接下来,我们来封装一个自定义控件MySpinerView,由于我没有去找向上箭头的图片资源,大家箭头自行替换。代码如下:
package com.newland.myspinerdemo;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.List;
/**
* 封装好的下拉列表,包括头部
*/
public class MySpinerView extends LinearLayout implements View.OnClickListener, MySpinerAdapter.IOnItemSelectListener {
private String mExampleString = "";
private int mExampleColor = Color.RED;
private float mExampleDimension = 0;
private Context context;
private RelativeLayout spiner;
private TextView tvSpiner;
private ImageView ivSpiner;
private ListnameList;
private MySpinerPopWindow mSpinerPopWindow;
public MySpinerView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
LayoutInflater.from(context).inflate(R.layout.sample_my_spiner_view, this);
init(attrs, 0);
spiner = (RelativeLayout) this.findViewById(R.id.spiner);
spiner.setOnClickListener(this);
tvSpiner = (TextView) this.findViewById(R.id.tv_spiner);
ivSpiner = (ImageView) this.findViewById(R.id.iv_spiner);
}
/**
* 设置弹出下拉表单的数据,在Activity那边得到控件后记得调用否则抛异常
* @param nameList
*/
public void setData(ListnameList) {
this.nameList = nameList;
mSpinerPopWindow = new MySpinerPopWindow(context);
mSpinerPopWindow.refreshData(nameList, 0);
mSpinerPopWindow.setItemListener(this); // 设置下拉列表item点击的监听,响应onItemClick回调函数
}
/**
* 头部点击事件
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.spiner:
showSpinWindow();
break;
}
}
/**
* 弹出下拉列表
*/
public void showSpinWindow() {
/**这里还有一步要做,就是让右边箭头向上。自己替换掉ivSpiner图片**/
mSpinerPopWindow.setWidth(((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth());
mSpinerPopWindow.showAsDropDown(tvSpiner);
}
/**
* 下拉列表项点击事件,把选中的值显示在界面上
* @param pos
*/
@Override
public void onItemClick(int pos) {
/**这里还有一步要做,就是让右边箭头还原向下。自己替换掉ivSpiner图片**/
if (pos >= 0 && pos <= nameList.size()) { // pos为-1就是弹窗消失,不管他
String value = nameList.get(pos);
tvSpiner.setText(value);
}
}
/**
* 初始化顶部显示数据
* @param txt
*/
public void initText(String txt){
tvSpiner.setText(txt);
}
}

自定义控件创建完毕,点击后弹出的下拉列表。

下拉列表实际上是一个PopWindow,里面有一个ListView,所以我们新建一个自定义弹窗PopWindow。代码如下:
package com.newland.myspinerdemo;
import java.util.List;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.PopupWindow;
/**
* 下拉列表弹窗
*/
public class MySpinerPopWindow extends PopupWindow implements OnItemClickListener {
private Context mContext;
private ListView mListView;
private MySpinerAdapter mAdapter;
private MySpinerAdapter.IOnItemSelectListener mItemSelectListener;
public MySpinerPopWindow(Context context) {
super(context);
mContext = context;
init();
}
/**
* 为MySpinnerView提供一个item点击事件的监听器,MySpinnerView实例调用此方法设置监听
* @param listener
*/
public void setItemListener(MySpinerAdapter.IOnItemSelectListener listener) {
mItemSelectListener = listener;
}
/**
* 初始化弹窗布局
*/
private void init() {
View view = LayoutInflater.from(mContext).inflate(R.layout.spiner_window_layout, null);
setContentView(view);
setWidth(LayoutParams.WRAP_CONTENT);
setHeight(LayoutParams.WRAP_CONTENT);
setFocusable(true);
ColorDrawable dw = new ColorDrawable(0x00);
setBackgroundDrawable(dw);
mListView = (ListView) view.findViewById(R.id.listview);
mAdapter = new MySpinerAdapter(mContext);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
this.setOnDismissListener(new OnDismissListener() { // 弹窗消失的监听
@Override
public void onDismiss() {
if (mItemSelectListener != null) {
mItemSelectListener.onItemClick(-1); // 弹窗消失,要让布局那边的箭头还原向下,所以那边还得判断一下,>=0的数据在显示,-1就忽略掉,箭头还原
}
}
});
}
/**
* 刷新下拉列表的数据
* @param list
* @param selIndex
*/
public void refreshData(Listlist, int selIndex) {
if (list != null && selIndex != -1) {
mAdapter.refreshData(list, selIndex);
}
}
/**
* 下拉列表ListView的点击事件。
* @param arg0
* @param view
* @param pos
* @param arg3
*/
@Override
public void onItemClick(AdapterViewarg0, View view, int pos, long arg3) {
dismiss();
if (mItemSelectListener != null) {
mItemSelectListener.onItemClick(pos); //点击后调用此方法,则MySpinerView会监听到(因为mItemSelectListener是MySpinerView那边设置的监听器)
}
}
}

既然是ListView,那么马上想到的就是适配器,那么我们接下来设置弹窗里面的ListView适配器,代码如下:
package com.newland.myspinerdemo;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MySpinerAdapterextends BaseAdapter {
private Context mContext;
private ListmObjects = new ArrayList();
private LayoutInflater mInflater;
public MySpinerAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* 刷新数据
* @param objects
* @param selIndex
*/
public void refreshData(Listobjects, int selIndex) {
mObjects = objects;
if (selIndex < 0) {
selIndex = 0;
}
if (selIndex >= mObjects.size()) {
selIndex = mObjects.size() - 1;
}
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public Object getItem(int pos) {
return mObjects.get(pos).toString();
}
@Override
public long getItemId(int pos) {
return pos;
}
@Override
public View getView(int pos, View convertView, ViewGroup arg2) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.spiner_item_layout, null);
viewHolder = new ViewHolder();
viewHolder.mTextView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
String item = (String) getItem(pos);
viewHolder.mTextView.setText(item);
return convertView;
}
public static class ViewHolder {
public TextView mTextView;
}
/**
* 提供一个设置点击事件监听的接口回调
*/
public interface IOnItemSelectListener {
void onItemClick(int pos);
}
}

好了,功能性的东西都完成了,来看看主页面布局

主页面布局由4个自定义控件(MySpinerView)组成,代码如下:
最后一步,编写Activity,代码如下
package com.newland.myspinerdemo;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity{
/**
* 四个下拉列表头部数据
*/
private String name1 = "课程类型";
private String name2 = "教练";
private String name3 = "卡路里";
private String name4 = "时间";
/**
* 四个下拉列表数据
*/
private ListnameList1 = new ArrayList();
private ListnameList2 = new ArrayList();
private ListnameList3 = new ArrayList (); private List nameList4 = new ArrayList (); /** * 四个自定义下拉列表 */ private MySpinerView mySpinerView1; private MySpinerView mySpinerView2; private MySpinerView mySpinerView3; private MySpinerView mySpinerView4; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setupViews(); } /** * 初始化四个下拉列表 */ private void setupViews() { mySpinerView1 = (MySpinerView)findViewById(R.id.mysv1); mySpinerView1.initText(name1); String[] names1 = { "高级课程", "中级课程", "所有课程" }; for (int i = 0; i < names1.length; i++) { nameList1.add(names1[i]); } mySpinerView1.setData(nameList1); mySpinerView2 = (MySpinerView)findViewById(R.id.mysv2); mySpinerView2.initText(name2); String[] names2 = {"小鱼","布拉特", "杰克逊", "菲尔顿", "希伯特"}; for (int i = 0; i < names2.length; i++) { nameList2.add(names2[i]); } mySpinerView2.setData(nameList2); mySpinerView3 = (MySpinerView)findViewById(R.id.mysv3); mySpinerView3.initText(name3); String[] names3 = {"10.0","20.0", "30.0", "40.0", "50.0"}; for (int i = 0; i < names3.length; i++) { nameList3.add(names3[i]); } mySpinerView3.setData(nameList3); mySpinerView4 = (MySpinerView)findViewById(R.id.mysv4); mySpinerView4.initText(name4); String[] names4 = {"1min","1hour", "1day", "1year", "forever"}; for (int i = 0; i < names4.length; i++) { nameList4.add(names4[i]); } mySpinerView4.setData(nameList4); } } 

大功告成~~~
附上源码下载链接: Android 自定义下拉列表 源码

Android 自定义下拉列表相关推荐

  1. Android自定义ViewGroup基本步骤

    1.自定义属性,获取自定义属性,可参考 ​ Android自定义View基本步骤 ​ 2.onMeasure() 方法,for循环测量子View,根据子View的宽高来计算自己的宽 高 3.onDra ...

  2. Android自定义View —— TypedArray

    在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...

  3. Android 自定义View —— Canvas

    上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...

  4. android 自定义loading,Android自定义动画-StarLoadingView

    今天来分享第二个自定义loading的动画,起了个名字叫 蹦跶的星星 ,还是老规矩先介绍,后上图. 实现效果在最后,GIF有点大,手机流量慎重. 介绍 首先声明做这个动画的初衷是为了学习和分享,所以从 ...

  5. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  6. android 自定义命名空间,Android自定义ActionBar实例

    本文实例讲述了android自定义actionbar的实现方法.分享给大家供大家参考.具体实现方法如下: android 3.0及以上已经有了actionbar的api,可以通过引入support p ...

  7. Android自定义View:ViewGroup(三)

    自定义ViewGroup本质是什么? 自定义ViewGroup本质上就干一件事--layout. layout 我们知道ViewGroup是一个组合View,它与普通的基本View(只要不是ViewG ...

  8. Android自定义视图四:定制onMeasure强制显示为方形

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  9. 自定义下拉列表(使用原始的事件监听机制),在搜索框中使用

    目录 背景: 效果: 注意事项: 完整代码: 背景: 搜索框中需要使用到动态获取热点搜索历史的功能,此时需要自定义下拉列表.select组件不能完全满足要求. 搜索框下拉列表支持键盘上下键及回车选择, ...

最新文章

  1. 科普丨你不得不知道的20个大数据术语
  2. vscode 全项目替换_利用vscode插件提升前端国际化开发效率
  3. MySQL之事务隔离级别--转载
  4. 去姥姥家需要做的事情
  5. SSL certificate problem, verify that the CA cert is OK. Details:
  6. 2016四季度 服务器收入和出货量双下滑
  7. HDOJ 2199 HDU 2199 Can you solve this equation? ACM 2199 IN HDU
  8. java helper 设计模式_必知必会的 Java 设计模式入门知识(十):外观模式
  9. CSS3学习笔记之loading动画
  10. 内存降价-可以入手啦
  11. c语言指针向前移动i个位置,C语言指针
  12. 情人节限定,cmd批处理浪漫表白
  13. 【英文SEO】Google网站流量分析
  14. ios wifi 定位_iOS中三种定位方式
  15. 索氏提取器使用注意_索氏提取法注意事项
  16. GIS+=地理信息+行业+大数据——纽约公开11亿条出租车和Uber原始数据下载及分析...
  17. 2016 年 50 个最佳的轻量级 JavaScript 框架和库一
  18. AAAI 2020 | 清华大学牛人为BabelNet同义词集预测Sememe建立多语言知识库
  19. 在小米实习到SP+转正
  20. 智慧景区视频监控方案

热门文章

  1. 哥德尔递归汉译和原始递归——哥德尔原著英译拆解汉译之七
  2. Visual Studio 2017, 2019 官网下载地址
  3. 图片素材类网站必备以图搜图、智能搜图识图图像搜索系统imgso,让素材网站更智能专业
  4. BlueTooth: 蓝牙Profile的概念和常见种类
  5. 企业为什么要上云?企业上云的好处和优势有哪些
  6. 最近企业上云是大趋势,那简单说说什么是企业上云?该如何上云?
  7. 分享免费与收费的主流报表工具推荐
  8. 京东区块链开源项目——JD Chain介绍及区块链白皮书发布
  9. html中蝴蝶飞飞怎么制作,【幼儿园折纸蝴蝶教案】手工折纸蝴蝶教案_幼儿园手工蝴蝶教案_亲亲宝贝网...
  10. 微信jssdk录音功能开发记录