Android开发笔记(一百二十一)列表弹窗PopupMenu和ListPopupWindow

PopupMenu

基本用法

PopupMenu是种显示位置不固定的弹出菜单,因为它显示在参照控件下方,所以展示位置随着参照控件的位置变化而变化。而其他几种菜单的显示位置都是固定的,比如说选项菜单Options固定显示在屏幕下方,上下文菜单ContextMenu固定显示在屏幕中央,溢出菜单OverflowMenu固定显示在屏幕右上角,有关其他菜单的详细说明参见《 Android开发笔记(六十五)多样的菜单 》。
下面是PopupMenu的常用方法说明:
构造函数 : 构造一个PopupMenu对象,并指定该对象的参照控件。
inflate : 根据指定的菜单资源文件,把具体的菜单项目填充到PopupMenu对象中。
setOnMenuItemClickListener : 设置菜单项的点击监听器。该监听器由接口OnMenuItemClickListener派生而来,要重写onMenuItemClick方法来实现菜单项点击事件。
show : 显示弹出菜单。
dismiss : 关闭弹出菜单。
setOnDismissListener : 设置弹出菜单的关闭监听器。


下面是PopupMenu的使用截图:



下面是PopupMenu的代码示例:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.Date;  
  2.   
  3. import com.example.exmpopup.util.Utils;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.view.MenuItem;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.Button;  
  11. import android.widget.PopupMenu;  
  12. import android.widget.PopupMenu.OnMenuItemClickListener;  
  13. import android.widget.TextView;  
  14. import android.widget.Toast;  
  15.   
  16. public class PopupMenuActivity extends Activity implements OnClickListener, OnMenuItemClickListener {  
  17.       
  18.     private TextView tv_show_menu;  
  19.     private PopupMenu mPopupMenu;  
  20.       
  21.     private String[] mFormatArray = {"yyyy-MM-dd HH:mm:ss""yyyy-MM-dd",  
  22.             "yyyy年MM月dd日HH时mm分ss秒""yyyy年MM月dd日"};  
  23.     private String mFormat = mFormatArray[0];  
  24.     private Date mNowTime = new Date();  
  25.   
  26.     @Override  
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.activity_menu);  
  30.   
  31.         tv_show_menu = (TextView) findViewById(R.id.tv_show_menu);  
  32.         Button btn_show_menu = (Button) findViewById(R.id.btn_show_menu);  
  33.         btn_show_menu.setOnClickListener(this);  
  34.         mPopupMenu = new PopupMenu(this, btn_show_menu);  
  35.         mPopupMenu.inflate(R.menu.main);  
  36.         //mPopupMenu.getMenuInflater().inflate(R.menu.main, mPopupMenu.getMenu());  
  37.         mPopupMenu.setOnMenuItemClickListener(this);  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onClick(View v) {  
  42.         if (v.getId() == R.id.btn_show_menu) {  
  43.             mPopupMenu.show();  
  44.         }  
  45.     }  
  46.   
  47.     @Override  
  48.     public boolean onMenuItemClick(MenuItem item) {  
  49.         int id = item.getItemId();  
  50.         if (id == R.id.menu_refresh) {  
  51.             mNowTime = new Date();  
  52.             tv_show_menu.setText("当前刷新时间: "+Utils.getFormatDateTime(mNowTime, mFormat));  
  53.         } else if (id == R.id.menu_about) {  
  54.             Toast.makeText(this"这个是PopupMenu的演示demo", Toast.LENGTH_LONG).show();  
  55.         } else if (id == R.id.menu_quit) {  
  56.             finish();  
  57.         }  
  58.         return true;  
  59.     }  
  60.       
  61. }  


新版PopupMenu

v7-appcompat库中引入了新版的PopupMenu,基本用法同旧版的PopupMenu。


使用新版PopupMenu时若出现如下的错误:java.lang.RuntimeException: Binary XML file line #17: You must supply a layout_height attribute.
则是因为使用v7-appcompat的控件,都要在AppCompatActivity中使用(比如Toolbar),并且要在AndroidManifest.xml中设置该Activity的android:theme为Theme.AppCompat.*派生的风格。有关v7-appcompat库的使用方法参见《 Android开发笔记(一百一十九)工具栏Toolbar 》。


v7-appcompat库中提供了新版PopupMenu,当然是做了部分功能完善,最主要的改进便是对子菜单的操作更加灵活,即可以由开发者自己定义在何时打开子菜单。下面是新版PopupMenu比旧版增加的调用方法说明:
onOpenSubMenu : 显示子菜单。
onCloseSubMenu : 关闭子菜单。
onMenuItemSelected : 选择菜单项。
getMenu : 获得Menu对象。之后便能给Menu对象调用addSubMenu方法添加子菜单;addSubMenu返回一个SubMenu对象,可调用SubMenu的add方法给子菜单添加具体项目。


下面是新版PopupMenu的代码示例:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.Date;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v7.app.AppCompatActivity;  
  5. import android.support.v7.view.menu.MenuBuilder;  
  6. import android.support.v7.widget.PopupMenu;  
  7. import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;  
  8. import android.view.MenuItem;  
  9. import android.view.SubMenu;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.Button;  
  13. import android.widget.TextView;  
  14. import android.widget.Toast;  
  15.   
  16. import com.example.exmpopup.util.Utils;  
  17.   
  18. public class NewPopupMenuActivity extends AppCompatActivity implements OnClickListener, OnMenuItemClickListener {  
  19.       
  20.     private TextView tv_show_menu_new;  
  21.     private PopupMenu mPopupMenu;  
  22.       
  23.     private String[] mFormatArray = {"yyyy-MM-dd HH:mm:ss""yyyy-MM-dd",  
  24.             "yyyy年MM月dd日HH时mm分ss秒""yyyy年MM月dd日"};  
  25.     private String mFormat = mFormatArray[0];  
  26.     private Date mNowTime = new Date();  
  27.     private SubMenu mSubMenu;  
  28.   
  29.     @Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.activity_menu_new);  
  33.   
  34.         tv_show_menu_new = (TextView) findViewById(R.id.tv_show_menu_new);  
  35.         Button btn_show_menu_new = (Button) findViewById(R.id.btn_show_menu_new);  
  36.         btn_show_menu_new.setOnClickListener(this);  
  37.         mPopupMenu = new PopupMenu(this, btn_show_menu_new);  
  38.         //mPopupMenu.inflate(R.menu.main); //两种inflate方式都可以  
  39.         mPopupMenu.getMenuInflater().inflate(R.menu.main, mPopupMenu.getMenu());  
  40.         mPopupMenu.setOnMenuItemClickListener(this);  
  41.         mSubMenu = mPopupMenu.getMenu().addSubMenu(09999"更多");  
  42.         mSubMenu.add(01110"ccc");  
  43.         mSubMenu.add(01121"cca");  
  44.     }  
  45.   
  46.     @Override  
  47.     public void onClick(View v) {  
  48.         if (v.getId() == R.id.btn_show_menu_new) {  
  49.             mPopupMenu.show();  
  50.         }  
  51.     }  
  52.   
  53.     @Override  
  54.     public boolean onMenuItemClick(MenuItem item) {  
  55.         int id = item.getItemId();  
  56.         if (id == R.id.menu_refresh) {  
  57.             mNowTime = new Date();  
  58.             tv_show_menu_new.setText("当前刷新时间: "+Utils.getFormatDateTime(mNowTime, mFormat));  
  59.         } else if (id == R.id.menu_about) {  
  60.             Toast.makeText(this"这个是PopupMenu的演示demo", Toast.LENGTH_SHORT).show();  
  61.             //点击“更多”会自动显示子菜单,点击“关于”也会由下面代码来显示子菜单  
  62.             mPopupMenu.onOpenSubMenu((MenuBuilder) mSubMenu);  
  63.         } else if (id == 111) {  
  64.             Toast.makeText(this"您点击了编号为"+id+"的子菜单项", Toast.LENGTH_SHORT).show();  
  65.         } else if (id == 112) {  
  66.             Toast.makeText(this"您点击了编号为"+id+"的子菜单项", Toast.LENGTH_SHORT).show();  
  67.         } else if (id == R.id.menu_quit) {  
  68.             finish();  
  69.         }  
  70.         return true;  
  71.     }  
  72.       
  73. }  


ListPopupWindow

基本用法

ListPopupWindow也是在参照控件下方显示列表窗口,不同的是,它在展示上更加灵活,开发者可以自定义列表弹窗的大小与样式。
下面是ListPopupWindow的常用方法说明:
setAdapter : 设置下拉列表的数据适配器。
setModal : 设置显示模式。通常设置为true。
setWidth : 设置下拉列表窗口的宽度。
setHeight : 设置下拉列表窗口的高度。
setAnchorView : 设置下拉列表的参照控件。下拉列表在显示时将展现在参照控件的下方,注意:如果不设置参照控件就直接调用show函数,系统不知道要把下拉列表在何处展示,只能是异常退出了。
setDropDownGravity : 设置下拉列表的对齐方式。Gravity.START表示与参照控件左侧对齐,Gravity.END表示与参照控件右侧对齐。注意:该函数只在4.4.2及以上版本中使用。
setOnItemClickListener : 设置列表项的点击监听器。
show : 显示下拉列表窗口。
dismiss : 关闭下拉列表窗口。
setOnDismissListener : 设置下拉列表的关闭监听器。


ListPopupWindow与EditText结合使用,效果上有点类似AutoCompleteTextView,即都会在编辑框下方弹出文本列表可供选择。但它们之间也有明显的区别:AutoCompleteTextView一旦设置适配器,则它会根据编辑框的文本来自动调整文本列表;而ListPopupWindow的文本列表是固定的,不会自动调整。


下面是ListPopupWindow的代码示例:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import android.annotation.TargetApi;  
  2. import android.app.Activity;  
  3. import android.os.Build;  
  4. import android.os.Bundle;  
  5. import android.view.Gravity;  
  6. import android.view.View;  
  7. import android.view.View.OnClickListener;  
  8. import android.view.ViewGroup.LayoutParams;  
  9. import android.widget.AdapterView;  
  10. import android.widget.AdapterView.OnItemClickListener;  
  11. import android.widget.ArrayAdapter;  
  12. import android.widget.Button;  
  13. import android.widget.EditText;  
  14. import android.widget.ListPopupWindow;  
  15.   
  16. @TargetApi(Build.VERSION_CODES.KITKAT)  
  17. public class ListPopupActivity extends Activity implements OnClickListener, OnItemClickListener {  
  18.   
  19.     private EditText et_list;  
  20.     private ListPopupWindow mPopup;  
  21.     private String[] mGoodArray={"pencil""potato""peanut""carrot""cabbage""cat"};  
  22.   
  23.     @Override  
  24.     protected void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.activity_list);  
  27.   
  28.         et_list = (EditText) findViewById(R.id.et_list);  
  29.         et_list.setOnClickListener(this);  
  30.         Button btn_show_list = (Button) findViewById(R.id.btn_show_list);  
  31.         btn_show_list.setOnClickListener(this);  
  32.           
  33.         mPopup = new ListPopupWindow(this);  
  34.         ArrayAdapter adapter = new ArrayAdapter(this, R.layout.spinner_item, mGoodArray);  
  35.         mPopup.setAdapter(adapter);  
  36.         mPopup.setWidth(LayoutParams.WRAP_CONTENT);  
  37.         mPopup.setHeight(LayoutParams.WRAP_CONTENT);  
  38.         mPopup.setModal(true);  
  39.         mPopup.setOnItemClickListener(this);  
  40.     }  
  41.   
  42.     @Override  
  43.     public void onClick(View v) {  
  44.         if (v.getId() == R.id.et_list) {  
  45.             if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.KITKAT) {  
  46.                 mPopup.setDropDownGravity(Gravity.END);  
  47.             }  
  48.             mPopup.setAnchorView(v);  
  49.             mPopup.show();  
  50.         } else if (v.getId() == R.id.btn_show_list) {  
  51.             if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.KITKAT) {  
  52.                 mPopup.setDropDownGravity(Gravity.START);  
  53.             }  
  54.             mPopup.setAnchorView(v);  
  55.             mPopup.show();  
  56.         }  
  57.     }  
  58.   
  59.     @Override  
  60.     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
  61.         et_list.setText(mGoodArray[position]);  
  62.         et_list.setSelection(et_list.getText().length());  
  63.         mPopup.dismiss();  
  64.     }  
  65.       
  66. }  


新旧ListPopupWindow的区别

v7-appcompat库中也提供了新版ListPopupWindow,据我观察在功能上没什么区别,主要是在弹窗的显示风格上有所差异,如旧版的ListPopupWindow有明显的窗口边框与边缘阴影,而新版的ListPopupWindow就没有窗口边框。


下面是旧版ListPopupWindow的UI,有窗口边框:



下面是新版ListPopupWindow的UI,没有窗口边框:



PopupMenu、ListPopupWindow和Spinner的区别

PopupMenu和ListPopupWindow同样都是列表弹窗,与spinnerMode="dropdown"的Spinner极其相似,都可以用来做下拉列表的选择弹窗,不过也有部分差异。下面是博主总结的它们之间的区别:
1、查看源码,会发现PopupMenu和Spinner内部都是使用ListPopupWindow实现下拉列表效果,所以ListPopupWindow是基础。
2、PopMenu的列表页面无法定制UI,只能显示光秃秃的文字;而ListPopupWindow和Spinner可以通过适配器来设置每项的布局风格,当然ListPopupWindow是最灵活的,不但可在左侧显示列表,还能在右侧显示列表。
3、PopMenu可通过子菜单实现多级菜单效果,而ListPopupWindow和Spinner只有一级列表。
4、ListPopupWindow和Spinner可以设置默认选中项,而PopMenu没有默认选中项。
5、Spinner既可以下拉列表来展示,也可以对话框来展示;而PopupMenu和ListPopupWindow只能以下拉列表展示。



点击下载本文用到的列表弹窗的工程代码



点此查看Android开发笔记的完整目录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值