Android開發筆記(一百二十一)列表彈窗PopupMenu和ListPopupWindow
PopupMenu
基本用法
PopupMenu是種顯示位置不固定的彈出選單,因為它顯示在參照控制元件下方,所以展示位置隨著參照控制元件的位置變化而變化。而其他幾種選單的顯示位置都是固定的,比如說選項選單Options固定顯示在螢幕下方,上下文選單ContextMenu固定顯示在螢幕中央,溢位選單OverflowMenu固定顯示在螢幕右上角,有關其他選單的詳細說明參見《Android開發筆記(六十五)多樣的選單》。下面是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庫的使用方法參見《Android開發筆記(一百一十九)工具欄Toolbar》。
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只能以下拉選單展示。
點選下載本文用到的列表彈窗的工程程式碼
點此檢視Android開發筆記的完整目錄
相關文章
- Android 開發之鎖屏彈窗Android
- EasyUI 筆記(3)彈出窗體UI筆記
- Android開發筆記(一百一十八)自定義懸浮窗Android筆記
- Xamarin開發筆記—裝置類&第三方彈窗的使用和注意事項筆記
- iOS開發之彈窗管理iOS
- Android之Window和彈窗問題Android
- Android開發筆記Android筆記
- iOS學習筆記--PresentedVC自定義彈窗iOS筆記
- iOS開發常用之 HUD 彈窗iOS
- Android彈窗二則: PopupWindow和AlertDialogAndroid
- Android彈窗二則:PopupWindow和AlertDialogAndroid
- Android PopupMenu基礎用法Android
- Android個人開發筆記Android筆記
- Android底部彈窗的正確開啟方式Android
- Android 開發學習筆記Android筆記
- iView之Modal(一級彈窗和二級彈窗)View
- 三,列表和陣列(筆記)陣列筆記
- 鴻蒙js開發7 鴻蒙分組列表和彈出menu選單鴻蒙JS
- react-native 仿原生自定義彈窗|iOS/Android 彈窗效果ReactiOSAndroid
- Android應用開發筆記(一)Android筆記
- vue外掛開發練習--實用彈窗Vue
- 開發:隨筆記錄之 HTML 彈出透明層事例筆記HTML
- 方法|rk3568開發平臺如何去除android正在啟動彈窗Android
- Android開發筆記[18]-使用本地模組Android筆記
- Android開發筆記[10]-關於頁Android筆記
- Android開發筆記[17]-桌面小部件Android筆記
- android開發學習筆記系列(1)-android起航Android筆記
- JS彈出視窗視窗的位置和大小JS
- Android開發筆記——TextView 多行時 ellipsizeAndroid筆記TextView
- Android開發筆記[13]-圖案密碼Android筆記密碼
- Android:PopWindow — 對Android的底部彈窗、頂部彈窗選單及自定義介面的使用封裝Android封裝
- 短視訊平臺開發,自定義一個彈窗樣式和內容
- 直播軟體開發,工具類的自定義彈窗效果
- 《Android藝術開發探索》學習筆記之View的事件體系(View的彈性滑動)Android筆記View事件
- 圖片彈窗和下載彈窗wordpress外掛下載-Facebox download
- Android開發筆記(一百一十九)工具欄ToolBarAndroid筆記
- android開發筆記之ADB Shell CommandsAndroid筆記
- android遊戲開發自學筆記3-2Android遊戲開發筆記