如何打造Android自定义的下拉列表框控件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何打造Android自定义的下拉列表框控件相关的知识,希望对你有一定的参考价值。

一、概述
android中的有个原生的下拉列表控件Spinner,但是这个控件有时候不符合我们自己的要求,
比如有时候我们需要类似windows 或者web网页中常见的那种下拉列表控件,类似下图这样的:

这个时候只有自己动手写一个了。其实实现起来不算很难,
本文实现的方案是采用TextView +ImageView+PopupWindow的组合方案。
先来看看我们的自己写的控件效果图吧:(源码在文章下面最后给出哈!)

二、自定义下拉列表框控件的实现
1. 自定义控件用到的布局文件和资源:
结果框的布局页面:dropdownlist_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="@+id/compound"
android:background="@drawable/dropdown_bg_selector" >

<TextView
android:id="@+id/text"
android:layout_width="250dp"
android:layout_height="40dp"
android:paddingLeft="10dp"
android:text="文本文字"
android:gravity="center_vertical"
android:textSize="14sp"
android:padding="5dp"
android:singleLine="true" />
<ImageView
android:id="@+id/btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_toRightOf="@+id/text"
android:src="@drawable/dropdown"
android:padding="5dp"
android:layout_centerVertical="true"
android:gravity="center"/>
</RelativeLayout>

下拉弹窗列表布局页面:dropdownlist_popupwindow.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
android:id="@+id/listView"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:divider="#666666"
android:dividerHeight="1dp"
></ListView>

</LinearLayout>

selector资源文件:
dropdown_list_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_item_press"/>
<item android:drawable="@color/dropdownlist_item"/>
</selector>

dropdown_bg_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_press"/>
<item android:drawable="@color/dropdownlist_bg"/>
</selector>

2. 自定义下拉列表框控件类的实现:
我们采用了TextView+ImageView+PopupWindow的组合方案,所以我的自定义控件需要重写ViewGroup,由于我们已经知道了,布局方向为竖直方向,所以这里,
我直接继承LinearLayout来写这个控件。具体实现代码如下:
package com.czm.xcdropdownlistview;

import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

@SuppressLint("NewApi")
/**
* 下拉列表框控件
* @author caizhiming
*
*/
public class XCDropDownListView extends LinearLayout

private TextView editText;
private ImageView imageView;
private PopupWindow popupWindow = null;
private ArrayList<String> dataList = new ArrayList<String>();
private View mView;
public XCDropDownListView(Context context)
this(context,null);
// TODO Auto-generated constructor stub

public XCDropDownListView(Context context, AttributeSet attrs)
this(context, attrs,0);
// TODO Auto-generated constructor stub

public XCDropDownListView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initView();


public void initView()
String infServie = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater layoutInflater;
layoutInflater = (LayoutInflater) getContext().getSystemService(infServie);
View view = layoutInflater.inflate(R.layout.dropdownlist_view, this,true);
editText= (TextView)findViewById(R.id.text);
imageView = (ImageView)findViewById(R.id.btn);
this.setOnClickListener(new OnClickListener()

@Override
public void onClick(View v)
// TODO Auto-generated method stub
if(popupWindow == null )
showPopWindow();
else
closePopWindow();


);

/**
* 打开下拉列表弹窗
*/
private void showPopWindow()
// 加载popupWindow的布局文件
String infServie = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater layoutInflater;
layoutInflater = (LayoutInflater) getContext().getSystemService(infServie);
View contentView = layoutInflater.inflate(R.layout.dropdownlist_popupwindow, null,false);
ListView listView = (ListView)contentView.findViewById(R.id.listView);

listView.setAdapter(new XCDropDownListAdapter(getContext(), dataList));
popupWindow = new PopupWindow(contentView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.color.transparent));
popupWindow.setOutsideTouchable(true);
popupWindow.showAsDropDown(this);

/**
* 关闭下拉列表弹窗
*/
private void closePopWindow()
popupWindow.dismiss();
popupWindow = null;

/**
* 设置数据
* @param list
*/
public void setItemsData(ArrayList<String> list)
dataList = list;
editText.setText(list.get(0).toString());

/**
* 数据适配器
* @author caizhiming
*
*/
class XCDropDownListAdapter extends BaseAdapter

Context mContext;
ArrayList<String> mData;
LayoutInflater inflater;
public XCDropDownListAdapter(Context ctx,ArrayList<String> data)
mContext = ctx;
mData = data;
inflater = LayoutInflater.from(mContext);

@Override
public int getCount()
// TODO Auto-generated method stub
return mData.size();


@Override
public Object getItem(int position)
// TODO Auto-generated method stub
return null;


@Override
public long getItemId(int position)
// TODO Auto-generated method stub
return position;


@Override
public View getView(int position, View convertView, ViewGroup parent)
// TODO Auto-generated method stub
// 自定义视图
ListItemView listItemView = null;
if (convertView == null)
// 获取list_item布局文件的视图
convertView = inflater.inflate(R.layout.dropdown_list_item, null);

listItemView = new ListItemView();
// 获取控件对象
listItemView.tv = (TextView) convertView
.findViewById(R.id.tv);

listItemView.layout = (LinearLayout) convertView.findViewById(R.id.layout_container);
// 设置控件集到convertView
convertView.setTag(listItemView);
else
listItemView = (ListItemView) convertView.getTag();


// 设置数据
listItemView.tv.setText(mData.get(position).toString());
final String text = mData.get(position).toString();
listItemView.layout.setOnClickListener(new OnClickListener()

@Override
public void onClick(View v)
// TODO Auto-generated method stub
editText.setText(text);
closePopWindow();

);
return convertView;



private static class ListItemView
TextView tv;
LinearLayout layout;




三、如何使用该自定义下拉列表框控件
使用该控件和使用普通的自带的控件一样,首先需要在布局文件中引用该控件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.czm.xcdropdownlistview.MainActivity"
tools:ignore="MergeRootFrame" >

<com.czm.xcdropdownlistview.XCDropDownListView
android:id="@+id/drop_down_list_view"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />

</RelativeLayout>

其次,就是在代码中使用该控件:
package com.czm.xcdropdownlistview;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
/**
* 使用下拉列表框控件 示例
* @author caizhiming
*
*/
public class MainActivity extends Activity

XCDropDownListView dropDownListView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

dropDownListView = (XCDropDownListView)findViewById(R.id.drop_down_list_view);
ArrayList<String> list = new ArrayList<String>();
for(int i = 0;i< 6;i++)
list.add("下拉列表项"+(i+1));

dropDownListView.setItemsData(list);





对了,这个控件中,我没有实现点击item项回调接口,这个可能对有些写惯了回调的可能觉得少了写什么的感觉,有兴趣的你可以自己添加相关回调操作哈,这个大家应该都会把。
参考技术A 1、水平布局一个TextView和一个ImageView(小黑箭头)
2、实现点击ImageView的单击事件,弹出PopupWindow
3、PopupWindow中实现下拉列表
关键代码示例:
1、布局

<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView/>
<ImageView />
</LinearLayout>
2、单击事件

image.setBackgroundResource(R.drawable.gerendang_jiantou);
image.setOnClickListener(new OnClickListener()
public void onClick(View v)
//弹出popupwindow

);
3、pupupwindow相关代码
ListView lv = new ListView(this);
adapter = new OptionsAdapter(context, datas); // 根据数据,设置下拉框显示
list.setAdapter(adapter);

/**
* 两种不同长度的下拉框,主要是为了适应屏幕的大小
*/
if (p_width > 0)
pWindow = new PopupWindow(v, par.getWidth(), 150);
else
pWindow = new PopupWindow(v, par.getWidth(), 300);

pWindow.setFocusable(true); //能够焦点获得
pWindow.setBackgroundDrawable(new BitmapDrawable()); //设置背景
pWindow.setOutsideTouchable(true); //外部点击关闭
pWindow.update(); //更新位置

下拉列表框Spinner-采用自定义布局文件作为Spinner样式

效果图,下拉列表显示的是name。

1.在activity_main.xml中添加Spinner控件
2.在layout文件夹中新建item_spinner.xml布局文件。

3.在MainActivity中添加一个内部类class User

4.完成MainActivity代码的编写

如果User的toString方法改为return phone,其他代码不变,则下拉列表中显示的是phone。

以上是关于如何打造Android自定义的下拉列表框控件的主要内容,如果未能解决你的问题,请参考以下文章

iOS常用刷新控件(下拉、上拉)详解

基于jquery扩展漂亮的下拉框——ComboBox

自定义Spinner下拉菜单(下拉列表框)样式

C# Winform自定义一个控件,一个按钮按下会显示ComboBox一样的下拉列表

下拉列表框Spinner-采用自定义布局文件作为Spinner样式

自定义SWT控件一之自定义单选下拉框