Android实现仿QQ登录可编辑下拉菜单

Android里,直接提供的Spinner控件虽然可以实现下拉菜单的效果,但其效果并不理想,很多时候我们需要类似手机QQ那样既可以在文本框中直接输入编辑文字,可以在下拉菜单中选中或者删除菜单选项,并且下拉菜单并不是以遮罩整个手机屏幕方式,而是以浮动在屏幕上的效果出现。下面呢,就来实现一下这些效果。

最后效果为:       

 

此次主要以EdiTextPopupWindowListViewAdapter来实现这种下拉效果。具体实现步骤就不一步步详细介绍了,直接贴完整代码吧,注释比较详细,相信都能看得懂。

 

 

//主界面Activity代码:

[html] view plaincopy
  1. public class SelectActivity extends Activity implements Callback {  
  2.     //PopupWindow对象  
  3.     private PopupWindow selectPopupWindownull;  
  4.     //自定义Adapter  
  5.     private OptionsAdapter optionsAdapter = null;  
  6.     //下拉框选项数据源  
  7.     private ArrayList<String> datas = new ArrayList<String>();;   
  8.     //下拉框依附组件  
  9.     private LinearLayout parent;  
  10.     //下拉框依附组件宽度,也将作为下拉框的宽度  
  11.     private int pwidth;   
  12.     //文本框  
  13.     private EditText et;  
  14.     //下拉箭头图片组件  
  15.     private ImageView image;  
  16.     //恢复数据源按钮  
  17.     private Button button;  
  18.     //展示所有下拉选项的ListView  
  19.     private ListView listView = null;   
  20.     //用来处理选中或者删除下拉项消息  
  21.     private Handler handler;  
  22.     //是否初始化完成标志    
  23.     private boolean flag = false;  
  24.       
  25.     @Override  
  26.     public void onCreate(Bundle savedInstanceState) {  
  27.         super.onCreate(savedInstanceState);  
  28.         setContentView(R.layout.select);  
  29.     }  
  30.   
  31.     /**  
  32.      * 没有在onCreate方法中调用initWedget(),而是在onWindowFocusChanged方法中调用,  
  33.      * 是因为initWedget()中需要获取PopupWindow浮动下拉框依附的组件宽度,在onCreate方法中是无法获取到该宽度的  
  34.      */  
  35.     @Override  
  36.     public void onWindowFocusChanged(boolean hasFocus) {  
  37.         super.onWindowFocusChanged(hasFocus);  
  38.         while(!flag){  
  39.             initWedget();  
  40.             flag = true;  
  41.         }  
  42.           
  43.     }  
  44.       
  45.     /**  
  46.      * 初始化界面控件  
  47.      */  
  48.     private void initWedget(){  
  49.         //初始化Handler,用来处理消息  
  50.         handler = new Handler(SelectActivity.this);  
  51.           
  52.         //初始化界面组件  
  53.         parent = (LinearLayout)findViewById(R.id.parent);  
  54.         et = (EditText)findViewById(R.id.edittext);  
  55.         image = (ImageView)findViewById(R.id.btn_select);  
  56.           
  57.           
  58.         //获取下拉框依附的组件宽度  
  59.         int width = parent.getWidth();  
  60.         pwidth = width;  
  61.           
  62.         //设置点击下拉箭头图片事件,点击弹出PopupWindow浮动下拉框  
  63.         image.setOnClickListener(new View.OnClickListener() {  
  64.             @Override  
  65.             public void onClick(View v) {  
  66.                 if(flag){  
  67.                     //显示PopupWindow窗口  
  68.                     popupWindwShowing();  
  69.                 }  
  70.             }  
  71.         });  
  72.           
  73.         //初始化PopupWindow  
  74.         initPopuWindow();  
  75.           
  76.         button = (Button)findViewById(R.id.refresh);  
  77.         //设置点击事件,恢复下拉框列表数据,没有什么作用,纯粹是为了方便多看几次效果而设置  
  78.         button.setOnClickListener(new View.OnClickListener() {  
  79.             @Override  
  80.             public void onClick(View v) {  
  81.                 initDatas();  
  82.                 optionsAdapter.notifyDataSetChanged();  
  83.             }  
  84.         });  
  85.     }  
  86.   
  87.     /**  
  88.      * 初始化填充Adapter所用List数据  
  89.      */  
  90.     private void initDatas(){  
  91.           
  92.          datas.clear();  
  93.            
  94.          datas.add("北京");  
  95.          datas.add("上海");  
  96.          datas.add("广州");  
  97.          datas.add("深圳");  
  98.          datas.add("重庆");  
  99.          datas.add("青岛");  
  100.          datas.add("石家庄");  
  101.     }  
  102.       
  103.      /**  
  104.      * 初始化PopupWindow  
  105.      */   
  106.     private void initPopuWindow(){   
  107.           
  108.         initDatas();  
  109.           
  110.         //PopupWindow浮动下拉框布局  
  111.         View loginwindow = (View)this.getLayoutInflater().inflate(R.layout.options, null);   
  112.         listView = (ListView) loginwindow.findViewById(R.id.list);   
  113.           
  114.         //设置自定义Adapter  
  115.         optionsAdapter = new OptionsAdapter(this, handler,datas);   
  116.         listView.setAdapter(optionsAdapter);   
  117.           
  118.         selectPopupWindow = new PopupWindow(loginwindow, pwidth,LayoutParams.WRAP_CONTENT, true);   
  119.           
  120.         selectPopupWindow.setOutsideTouchable(true);   
  121.           
  122.         //这一句是为了实现弹出PopupWindow后,当点击屏幕其他部分及Back键时PopupWindow会消失,  
  123.         //没有这一句则效果不能出来,但并不会影响背景  
  124.         //本人能力极其有限,不明白其原因,还望高手、知情者指点一下  
  125.         selectPopupWindow.setBackgroundDrawable(new BitmapDrawable());    
  126.     }   
  127.   
  128.       
  129.       
  130.     /**  
  131.      * 显示PopupWindow窗口  
  132.      *   
  133.      * @param popupwindow  
  134.      */   
  135.     public void popupWindwShowing() {   
  136.        //将selectPopupWindow作为parent的下拉框显示,并指定selectPopupWindow在Y方向上向上偏移3pix,  
  137.        //这是为了防止下拉框与文本框之间产生缝隙,影响界面美化  
  138.        //(是否会产生缝隙,及产生缝隙的大小,可能会根据机型、Android系统版本不同而异吧,不太清楚)  
  139.        selectPopupWindow.showAsDropDown(parent,0,-3);   
  140.     }   
  141.        
  142.     /**  
  143.      * PopupWindow消失  
  144.      */   
  145.     public void dismiss(){   
  146.         selectPopupWindow.dismiss();   
  147.     }  
  148.   
  149.     /**  
  150.      * 处理Hander消息  
  151.      */  
  152.     @Override  
  153.     public boolean handleMessage(Message message) {  
  154.         Bundle data = message.getData();  
  155.         switch(message.what){  
  156.             case 1:  
  157.                 //选中下拉项,下拉框消失  
  158.                 int selIndex = data.getInt("selIndex");  
  159.                 et.setText(datas.get(selIndex));  
  160.                 dismiss();  
  161.                 break;  
  162.             case 2:  
  163.                 //移除下拉项数据  
  164.                 int delIndex = data.getInt("delIndex");  
  165.                 datas.remove(delIndex);  
  166.                 //刷新下拉列表  
  167.                 optionsAdapter.notifyDataSetChanged();  
  168.                 break;  
  169.         }  
  170.         return false;  
  171.     }   
  172. }  


自定义适配器Adapter代码:

[java] view plaincopy
  1. public class OptionsAdapter extends BaseAdapter {  
  2.   
  3.     private ArrayList<String> list = new ArrayList<String>();   
  4.     private Activity activity = null;   
  5.     private Handler handler;  
  6.       
  7.     /** 
  8.      * 自定义构造方法 
  9.      * @param activity 
  10.      * @param handler 
  11.      * @param list 
  12.      */  
  13.     public OptionsAdapter(Activity activity,Handler handler,ArrayList<String> list){  
  14.         this.activity = activity;  
  15.         this.handler = handler;  
  16.         this.list = list;  
  17.     }  
  18.       
  19.     @Override  
  20.     public int getCount() {  
  21.         return list.size();  
  22.     }  
  23.   
  24.     @Override  
  25.     public Object getItem(int position) {  
  26.         return list.get(position);  
  27.     }  
  28.   
  29.     @Override  
  30.     public long getItemId(int position) {  
  31.         return position;  
  32.     }  
  33.   
  34.     @Override  
  35.     public View getView(final int position, View convertView, ViewGroup parent) {  
  36.         ViewHolder holder = null;   
  37.         if (convertView == null) {   
  38.             holder = new ViewHolder();   
  39.             //下拉项布局  
  40.             convertView = LayoutInflater.from(activity).inflate(R.layout.option_item, null);   
  41.             holder.textView = (TextView) convertView.findViewById(R.id.item_text);   
  42.             holder.imageView = (ImageView) convertView.findViewById(R.id.delImage);   
  43.               
  44.             convertView.setTag(holder);   
  45.         } else {   
  46.             holder = (ViewHolder) convertView.getTag();   
  47.         }   
  48.           
  49.         holder.textView.setText(list.get(position));  
  50.           
  51.         //为下拉框选项文字部分设置事件,最终效果是点击将其文字填充到文本框  
  52.         holder.textView.setOnClickListener(new View.OnClickListener() {  
  53.             @Override  
  54.             public void onClick(View v) {  
  55.                 Message msg = new Message();  
  56.                 Bundle data = new Bundle();  
  57.                 //设置选中索引  
  58.                 data.putInt("selIndex", position);  
  59.                 msg.setData(data);  
  60.                 msg.what = 1;  
  61.                 //发出消息  
  62.                 handler.sendMessage(msg);  
  63.             }  
  64.         });  
  65.           
  66.         //为下拉框选项删除图标部分设置事件,最终效果是点击将该选项删除  
  67.         holder.imageView.setOnClickListener(new View.OnClickListener() {  
  68.             @Override  
  69.             public void onClick(View v) {  
  70.                 Message msg = new Message();  
  71.                 Bundle data = new Bundle();  
  72.                 //设置删除索引  
  73.                 data.putInt("delIndex", position);  
  74.                 msg.setData(data);  
  75.                 msg.what = 2;  
  76.                 //发出消息  
  77.                 handler.sendMessage(msg);  
  78.             }  
  79.         });  
  80.           
  81.         return convertView;   
  82.     }  
  83.   
  84. }  
  85.   
  86.   
  87. class ViewHolder {   
  88.     TextView textView;   
  89.     ImageView imageView;   
  90. }   


 


 

主界面布局select.xml文件:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:background="#EEEED1"  
  7.     >  
  8. <LinearLayout android:id="@+id/parent" android:layout_width="wrap_content"   
[html] view plaincopy
  1. android:layout_height="wrap_content" android:orientation="horizontal"   
[html] view plaincopy
  1.      android:layout_marginTop="50dp" android:layout_marginLeft="30dp">  
  2. <EditText android:id="@+id/edittext" android:layout_width="200dp"  android:singleLine="true"  
  3.     android:layout_height="40dp" android:background="@drawable/bg1" android:paddingLeft="3dp"/>  
  4. <ImageView android:id="@+id/btn_select" android:layout_width="30dp" android:layout_height="40dp"   
  5.     android:src="@drawable/img1" android:scaleType="fitXY"/>  
  6. </LinearLayout>  
  7. <Button android:id="@+id/refresh" android:layout_width="wrap_content" android:layout_height="45dp"  
  8.     android:text="恢复" android:textColor="#000000" android:textSize="20sp"   
[html] view plaincopy
  1. android:layout_marginTop="30dp" android:layout_marginLeft="30dp"/>  
  2. lt;/LinearLayout>  

 

 

PopupWindow浮动下拉框布局options.xml文件:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content"  
  6.     android:gravity="center_horizontal"  
  7.     >  
  8. <ListView android:id="@+id/list" android:layout_width="fill_parent"  
  9.     android:layout_height="wrap_content" android:cacheColorHint="#00000000">  
  10. </ListView>  
  11. </LinearLayout>  


 

下拉选项布局option_item.xml文件:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:background="#235654"  
  6.     >  
  7. <RelativeLayout  
  8.     android:layout_width="wrap_content"  
  9.     android:layout_height="wrap_content"  
  10.     android:gravity="center_vertical"  
  11.     android:minHeight="40dp"  
  12.     >  
  13. <ImageView android:id="@+id/delImage" android:layout_width="20dp"  
[html] view plaincopy
  1.      android:layout_height="wrap_content" android:src="@drawable/del" android:textSize="18sp"  
  2.     android:layout_alignParentRight="true" android:layout_marginRight="10dp"/>  
  3. <TextView android:id="@+id/item_text"  android:layout_height="wrap_content"  
  4.      android:layout_width="fill_parent" android:layout_toLeftOf="@id/delImage"  
  5.       android:paddingLeft="5dp" android:layout_alignParentLeft="true"></TextView>  
  6. </RelativeLayout>  
  7. </LinearLayout>  



阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页