前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(一百二十一)列表弹窗PopupMenu和ListPopupWindow

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

作者头像
aqi00
发布2019-01-18 14:37:48
3.3K0
发布2019-01-18 14:37:48
举报
文章被收录于专栏:老欧说安卓

PopupMenu

基本用法

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

下面是PopupMenu的代码示例:

代码语言:javascript
复制
import java.util.Date;

import com.example.exmpopup.util.Utils;

import android.app.Activity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.TextView;
import android.widget.Toast;

public class PopupMenuActivity extends Activity implements OnClickListener, OnMenuItemClickListener {
	
	private TextView tv_show_menu;
	private PopupMenu mPopupMenu;
	
	private String[] mFormatArray = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd",
			"yyyy年MM月dd日HH时mm分ss秒", "yyyy年MM月dd日"};
	private String mFormat = mFormatArray[0];
	private Date mNowTime = new Date();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_menu);

		tv_show_menu = (TextView) findViewById(R.id.tv_show_menu);
		Button btn_show_menu = (Button) findViewById(R.id.btn_show_menu);
		btn_show_menu.setOnClickListener(this);
		mPopupMenu = new PopupMenu(this, btn_show_menu);
		mPopupMenu.inflate(R.menu.main);
		//mPopupMenu.getMenuInflater().inflate(R.menu.main, mPopupMenu.getMenu());
		mPopupMenu.setOnMenuItemClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.btn_show_menu) {
	    	mPopupMenu.show();
		}
	}

	@Override
	public boolean onMenuItemClick(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.menu_refresh) {
			mNowTime = new Date();
			tv_show_menu.setText("当前刷新时间: "+Utils.getFormatDateTime(mNowTime, mFormat));
        } else if (id == R.id.menu_about) {
			Toast.makeText(this, "这个是PopupMenu的演示demo", Toast.LENGTH_LONG).show();
        } else if (id == R.id.menu_quit) {
			finish();
        }
		return true;
	}
    
}

新版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的代码示例:

代码语言:javascript
复制
import java.util.Date;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.menu.MenuBuilder;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.example.exmpopup.util.Utils;

public class NewPopupMenuActivity extends AppCompatActivity implements OnClickListener, OnMenuItemClickListener {
	
	private TextView tv_show_menu_new;
	private PopupMenu mPopupMenu;
	
	private String[] mFormatArray = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd",
			"yyyy年MM月dd日HH时mm分ss秒", "yyyy年MM月dd日"};
	private String mFormat = mFormatArray[0];
	private Date mNowTime = new Date();
	private SubMenu mSubMenu;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_menu_new);

		tv_show_menu_new = (TextView) findViewById(R.id.tv_show_menu_new);
		Button btn_show_menu_new = (Button) findViewById(R.id.btn_show_menu_new);
		btn_show_menu_new.setOnClickListener(this);
		mPopupMenu = new PopupMenu(this, btn_show_menu_new);
		//mPopupMenu.inflate(R.menu.main); //两种inflate方式都可以
		mPopupMenu.getMenuInflater().inflate(R.menu.main, mPopupMenu.getMenu());
		mPopupMenu.setOnMenuItemClickListener(this);
		mSubMenu = mPopupMenu.getMenu().addSubMenu(0, 999, 9, "更多");
		mSubMenu.add(0, 111, 0, "ccc");
		mSubMenu.add(0, 112, 1, "cca");
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.btn_show_menu_new) {
	    	mPopupMenu.show();
		}
	}

	@Override
	public boolean onMenuItemClick(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.menu_refresh) {
			mNowTime = new Date();
			tv_show_menu_new.setText("当前刷新时间: "+Utils.getFormatDateTime(mNowTime, mFormat));
        } else if (id == R.id.menu_about) {
			Toast.makeText(this, "这个是PopupMenu的演示demo", Toast.LENGTH_SHORT).show();
			//点击“更多”会自动显示子菜单,点击“关于”也会由下面代码来显示子菜单
			mPopupMenu.onOpenSubMenu((MenuBuilder) mSubMenu);
        } else if (id == 111) {
			Toast.makeText(this, "您点击了编号为"+id+"的子菜单项", Toast.LENGTH_SHORT).show();
        } else if (id == 112) {
			Toast.makeText(this, "您点击了编号为"+id+"的子菜单项", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.menu_quit) {
			finish();
        }
		return true;
	}
    
}

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的代码示例:

代码语言:javascript
复制
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListPopupWindow;

@TargetApi(Build.VERSION_CODES.KITKAT)
public class ListPopupActivity extends Activity implements OnClickListener, OnItemClickListener {

	private EditText et_list;
	private ListPopupWindow mPopup;
	private String[] mGoodArray={"pencil", "potato", "peanut", "carrot", "cabbage", "cat"};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_list);

		et_list = (EditText) findViewById(R.id.et_list);
		et_list.setOnClickListener(this);
		Button btn_show_list = (Button) findViewById(R.id.btn_show_list);
		btn_show_list.setOnClickListener(this);
		
		mPopup = new ListPopupWindow(this);
		ArrayAdapter adapter = new ArrayAdapter(this, R.layout.spinner_item, mGoodArray);
		mPopup.setAdapter(adapter);
		mPopup.setWidth(LayoutParams.WRAP_CONTENT);
		mPopup.setHeight(LayoutParams.WRAP_CONTENT);
		mPopup.setModal(true);
		mPopup.setOnItemClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.et_list) {
			if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.KITKAT) {
				mPopup.setDropDownGravity(Gravity.END);
			}
			mPopup.setAnchorView(v);
			mPopup.show();
		} else if (v.getId() == R.id.btn_show_list) {
			if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.KITKAT) {
				mPopup.setDropDownGravity(Gravity.START);
			}
			mPopup.setAnchorView(v);
			mPopup.show();
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		et_list.setText(mGoodArray[position]);
		et_list.setSelection(et_list.getText().length());
		mPopup.dismiss();
	}
	
}

新旧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开发笔记的完整目录

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年08月29日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PopupMenu
    • 基本用法
      • 新版PopupMenu
      • ListPopupWindow
        • 基本用法
          • 新旧ListPopupWindow的区别
          • PopupMenu、ListPopupWindow和Spinner的区别
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档