Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發筆記(一百二十一)列表彈窗PopupMenu和ListPopupWindow

Android開發筆記(一百二十一)列表彈窗PopupMenu和ListPopupWindow

編輯:關於Android編程

PopupMenu

基本用法

PopupMenu是種顯示位置不固定的彈出菜單,因為它顯示在參照控件下方,所以展示位置隨著參照控件的位置變化而變化。而其他幾種菜單的顯示位置都是固定的,比如說選項菜單Options固定顯示在屏幕下方,上下文菜單ContextMenu固定顯示在屏幕中央,溢出菜單OverflowMenu固定顯示在屏幕右上角
下面是PopupMenu的常用方法說明:
構造函數 : 構造一個PopupMenu對象,並指定該對象的參照控件。
inflate : 根據指定的菜單資源文件,把具體的菜單項目填充到PopupMenu對象中。
setOnMenuItemClickListener : 設置菜單項的點擊監聽器。該監聽器由接口OnMenuItemClickListener派生而來,要重寫onMenuItemClick方法來實現菜單項點擊事件。
show : 顯示彈出菜單。
dismiss : 關閉彈出菜單。
setOnDismissListener : 設置彈出菜單的關閉監聽器。


下面是PopupMenu的使用截圖:
\


下面是PopupMenu的代碼示例:
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庫中提供了新版PopupMenu,當然是做了部分功能完善,最主要的改進便是對子菜單的操作更加靈活,即可以由開發者自己定義在何時打開子菜單。下面是新版PopupMenu比舊版增加的調用方法說明:
onOpenSubMenu : 顯示子菜單。
onCloseSubMenu : 關閉子菜單。
onMenuItemSelected : 選擇菜單項。
getMenu : 獲得Menu對象。之後便能給Menu對象調用addSubMenu方法添加子菜單;addSubMenu返回一個SubMenu對象,可調用SubMenu的add方法給子菜單添加具體項目。


下面是新版PopupMenu的代碼示例:
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的代碼示例:
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只能以下拉列表展示。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved