在android裡,直接提供的spinner控件雖然可以實作下拉菜單的效果,但其效果并不理想,很多時候我們需要類似手機qq那樣既可以在文本框中直接輸入編輯文字,可以在下拉菜單中選中或者删除菜單選項,并且下拉菜單并不是以遮罩整個手機螢幕方式,而是以浮動在螢幕上的效果出現。下面呢,就來實作一下這些效果。
最後效果為:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iMzUjMfZDOzQzM5EDNzEzLcBTMvw1NwITMwIzLcNHZh9GbwV3LcRXZu5ibkN3YukXbvw1LcpDc0RHaiojIsJye.png)
此次主要以editext、popupwindow、listview及adapter來實作這種下拉效果。具體實作步驟就不一步步詳細介紹了,直接貼完整代碼吧,注釋比較詳細,相信都能看得懂。
//主界面activity代碼:
[html] view
plaincopy
public class selectactivity extends activity implements callback {
//popupwindow對象
private popupwindow selectpopupwindow= null;
//自定義adapter
private optionsadapter optionsadapter = null;
//下拉框選項資料源
private arraylist<string> datas = new arraylist<string>();;
//下拉框依附元件
private linearlayout parent;
//下拉框依附元件寬度,也将作為下拉框的寬度
private int pwidth;
//文本框
private edittext et;
//下拉箭頭圖檔元件
private imageview image;
//恢複資料源按鈕
private button button;
//展示所有下拉選項的listview
private listview listview = null;
//用來處理選中或者删除下拉項消息
private handler handler;
//是否初始化完成标志
private boolean flag = false;
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.select);
}
/**
* 沒有在oncreate方法中調用initwedget(),而是在onwindowfocuschanged方法中調用,
* 是因為initwedget()中需要擷取popupwindow浮動下拉框依附的元件寬度,在oncreate方法中是無法擷取到該寬度的
*/
public void onwindowfocuschanged(boolean hasfocus) {
super.onwindowfocuschanged(hasfocus);
while(!flag){
initwedget();
flag = true;
}
* 初始化界面控件
private void initwedget(){
//初始化handler,用來處理消息
handler = new handler(selectactivity.this);
//初始化界面元件
parent = (linearlayout)findviewbyid(r.id.parent);
et = (edittext)findviewbyid(r.id.edittext);
image = (imageview)findviewbyid(r.id.btn_select);
//擷取下拉框依附的元件寬度
int width = parent.getwidth();
pwidth = width;
//設定點選下拉箭頭圖檔事件,點選彈出popupwindow浮動下拉框
image.setonclicklistener(new view.onclicklistener() {
@override
public void onclick(view v) {
if(flag){
//顯示popupwindow視窗
popupwindwshowing();
}
}
});
//初始化popupwindow
initpopuwindow();
button = (button)findviewbyid(r.id.refresh);
//設定點選事件,恢複下拉框清單資料,沒有什麼作用,純粹是為了友善多看幾次效果而設定
button.setonclicklistener(new view.onclicklistener() {
initdatas();
optionsadapter.notifydatasetchanged();
* 初始化填充adapter所用list資料
private void initdatas(){
datas.clear();
datas.add("北京");
datas.add("上海");
datas.add("廣州");
datas.add("深圳");
datas.add("重慶");
datas.add("青島");
datas.add("石家莊");
/**
* 初始化popupwindow
*/
private void initpopuwindow(){
initdatas();
//popupwindow浮動下拉框布局
view loginwindow = (view)this.getlayoutinflater().inflate(r.layout.options, null);
listview = (listview) loginwindow.findviewbyid(r.id.list);
//設定自定義adapter
optionsadapter = new optionsadapter(this, handler,datas);
listview.setadapter(optionsadapter);
selectpopupwindow = new popupwindow(loginwindow, pwidth,layoutparams.wrap_content, true);
selectpopupwindow.setoutsidetouchable(true);
//這一句是為了實作彈出popupwindow後,當點選螢幕其他部分及back鍵時popupwindow會消失,
//沒有這一句則效果不能出來,但并不會影響背景
//本人能力極其有限,不明白其原因,還望高手、知情者指點一下
selectpopupwindow.setbackgrounddrawable(new bitmapdrawable());
}
* 顯示popupwindow視窗
*
* @param popupwindow
public void popupwindwshowing() {
//将selectpopupwindow作為parent的下拉框顯示,并指定selectpopupwindow在y方向上向上偏移3pix,
//這是為了防止下拉框與文本框之間産生縫隙,影響界面美化
//(是否會産生縫隙,及産生縫隙的大小,可能會根據機型、android系統版本不同而異吧,不太清楚)
selectpopupwindow.showasdropdown(parent,0,-3);
* popupwindow消失
public void dismiss(){
selectpopupwindow.dismiss();
* 處理hander消息
public boolean handlemessage(message message) {
bundle data = message.getdata();
switch(message.what){
case 1:
//選中下拉項,下拉框消失
int selindex = data.getint("selindex");
et.settext(datas.get(selindex));
dismiss();
break;
case 2:
//移除下拉項資料
int delindex = data.getint("delindex");
datas.remove(delindex);
//重新整理下拉清單
return false;
}
自定義擴充卡adapter代碼:
[java] view
public class optionsadapter extends baseadapter {
private arraylist<string> list = new arraylist<string>();
private activity activity = null;
/**
* 自定義構造方法
* @param activity
* @param handler
* @param list
public optionsadapter(activity activity,handler handler,arraylist<string> list){
this.activity = activity;
this.handler = handler;
this.list = list;
public int getcount() {
return list.size();
public object getitem(int position) {
return list.get(position);
public long getitemid(int position) {
return position;
public view getview(final int position, view convertview, viewgroup parent) {
viewholder holder = null;
if (convertview == null) {
holder = new viewholder();
//下拉項布局
convertview = layoutinflater.from(activity).inflate(r.layout.option_item, null);
holder.textview = (textview) convertview.findviewbyid(r.id.item_text);
holder.imageview = (imageview) convertview.findviewbyid(r.id.delimage);
convertview.settag(holder);
} else {
holder = (viewholder) convertview.gettag();
}
holder.textview.settext(list.get(position));
//為下拉框選項文字部分設定事件,最終效果是點選将其文字填充到文本框
holder.textview.setonclicklistener(new view.onclicklistener() {
message msg = new message();
bundle data = new bundle();
//設定選中索引
data.putint("selindex", position);
msg.setdata(data);
msg.what = 1;
//發出消息
handler.sendmessage(msg);
//為下拉框選項删除圖示部分設定事件,最終效果是點選将該選項删除
holder.imageview.setonclicklistener(new view.onclicklistener() {
//設定删除索引
data.putint("delindex", position);
msg.what = 2;
return convertview;
class viewholder {
textview textview;
imageview imageview;
}
主界面布局select.xml檔案:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#eeeed1"
>
<linearlayout android:id="@+id/parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:orientation="horizontal"
android:layout_margintop="50dp" android:layout_marginleft="30dp">
<edittext android:id="@+id/edittext" android:layout_width="200dp" android:singleline="true"
android:layout_height="40dp" android:background="@drawable/bg1" android:paddingleft="3dp"/>
<imageview android:id="@+id/btn_select" android:layout_width="30dp" android:layout_height="40dp"
android:src="@drawable/img1" android:scaletype="fitxy"/>
</linearlayout>
<button android:id="@+id/refresh" android:layout_width="wrap_content" android:layout_height="45dp"
android:text="恢複" android:textcolor="#000000" android:textsize="20sp"
android:layout_margintop="30dp" android:layout_marginleft="30dp"/>
lt;/linearlayout>
popupwindow浮動下拉框布局options.xml檔案:
android:layout_height="wrap_content"
android:gravity="center_horizontal"
<listview android:id="@+id/list" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:cachecolorhint="#00000000">
</listview>
下拉選項布局option_item.xml檔案:
android:background="#235654"
<relativelayout
android:layout_width="wrap_content"
android:gravity="center_vertical"
android:minheight="40dp"
<imageview android:id="@+id/delimage" android:layout_width="20dp"
android:layout_height="wrap_content" android:src="@drawable/del" android:textsize="18sp"
android:layout_alignparentright="true" android:layout_marginright="10dp"/>
<textview android:id="@+id/item_text" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_toleftof="@id/delimage"
android:paddingleft="5dp" android:layout_alignparentleft="true"></textview>
</relativelayout>