在Android里,直接提供的Spinner控件虽然可以实现下拉菜单的效果,但其效果并不理想,很多时候我们需要类似手机QQ那样既可以在文本框中直接输入编辑文字,可以在下拉菜单中选中或者删除菜单选项,并且下拉菜单并不是以遮罩整个手机屏幕方式,而是以浮动在屏幕上的效果出现。下面呢,就来实现一下这些效果。
最后效果为:
此次主要以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方法中是无法获取到该宽度的
- */
- @Override
- 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() {
- @Override
- public void onClick(View v) {
- 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消息
- */
- @Override
- 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);
- //刷新下拉列表
- optionsAdapter.notifyDataSetChanged();
- break;
- }
- return false;
- }
- }
自定义适配器Adapter代码:
[java] view
plaincopy
- public class OptionsAdapter extends BaseAdapter {
- private ArrayList<String> list = new ArrayList<String>();
- private Activity activity = null;
- private Handler handler;
- /**
- * 自定义构造方法
- * @param activity
- * @param handler
- * @param list
- */
- public OptionsAdapter(Activity activity,Handler handler,ArrayList<String> list){
- this.activity = activity;
- this.handler = handler;
- this.list = list;
- }
- @Override
- public int getCount() {
- return list.size();
- }
- @Override
- public Object getItem(int position) {
- return list.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- 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() {
- @Override
- public void onClick(View v) {
- 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() {
- @Override
- public void onClick(View v) {
- Message msg = new Message();
- Bundle data = new Bundle();
- //设置删除索引
- data.putInt("delIndex", position);
- msg.setData(data);
- msg.what = 2;
- //发出消息
- handler.sendMessage(msg);
- }
- });
- return convertView;
- }
- }
- class ViewHolder {
- TextView textView;
- ImageView imageView;
- }
主界面布局select.xml文件:
[html] view
plaincopy
- <?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"
[html] view
plaincopy
- android:layout_height="wrap_content" android:orientation="horizontal"
[html] view
plaincopy
- 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"
[html] view
plaincopy
- android:layout_marginTop="30dp" android:layout_marginLeft="30dp"/>
- lt;/LinearLayout>
PopupWindow浮动下拉框布局options.xml文件:
[html] view
plaincopy
- <?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="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>
- </LinearLayout>
下拉选项布局option_item.xml文件:
[html] view
plaincopy
- <?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:background="#235654"
- >
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:minHeight="40dp"
- >
- <ImageView android:id="@+id/delImage" android:layout_width="20dp"
[html] view
plaincopy
- 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>
- </LinearLayout>
时间: 2024-09-27 12:03:40