編輯:關於Android編程
在本文當中,我將會與大家分享一個封裝了PopupWindow實現彈出菜單的類,並說明它的實現與使用。
因對界面的需求,android原生的彈出菜單已不能滿足我們的需求,自定義菜單成了我們的唯一選擇,在本文當中,我將與大家分享如何使用PopupWindow實現彈出菜單。
PopupWindow可以說是一個浮動在Activity之上的容器,通常用來顯示自定義的視圖。比如像自動完成輸入框AutoCompleteTextView,它的提示列表就是使用PopupWindow來實現的。下面的抽象類PopMenu封裝了使用PopupWindow實現彈出菜單的UI邏輯,但不包括界面布局的設定。
/* * Date: 14-6-13 * Project: Parking Lay-by */ package cn.irains.access.v2.common; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.PopupWindow; import java.util.ArrayList; /** * 對彈出菜單的封裝. * Author: msdx ([email protected]) * Time: 14-6-13 下午1:51 */ public abstract class PopMenu { /** * 上下文. */ private Context mContext; /** * 菜單項 */ private ArrayList- mItemList; /** * 列表適配器. */ private ArrayAdapter
- mAdapter; /** * 菜單選擇監聽. */ private OnItemSelectedListener mListener; /** * 列表. */ private ListView mListView; /** * 彈出窗口. */ private PopupWindow mPopupWindow; public PopMenu(Context context) { mContext = context; mItemList = new ArrayList
- (2); View view = onCreateView(context); view.setFocusableInTouchMode(true); mAdapter = onCreateAdapter(context, mItemList); mListView = findListView(view); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView> parent, View view, int position, long id) { Item item = mAdapter.getItem(position); if (mListener != null) { mListener.selected(view, item, position); } mPopupWindow.dismiss(); } }); view.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_MENU && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); return true; } return false; } }); mPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); mPopupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000)); } /** * 菜單的界面視圖. * * @param context * @return */ protected abstract View onCreateView(Context context); /** * 菜單界面視圖中的列表. * * @param view * @return */ protected abstract ListView findListView(View view); /** * 菜單列表中的適配器. * * @param context * @param itemList 表示所有菜單項. * @return */ protected abstract ArrayAdapter
- onCreateAdapter(Context context, ArrayList
- itemList); /** * 添加菜單項. * * @param text 菜單項文字內容. * @param id 菜單項的ID */ public void addItem(String text, int id) { mItemList.add(new Item(text, id)); mAdapter.notifyDataSetChanged(); } /** * 添加菜單項. * * @param resId 菜單項文字內容的資源ID * @param id 菜單項的ID. */ public void addItem(int resId, int id) { addItem(mContext.getString(resId), id); } /** * 作為指定View的下拉控制顯示. * * @param parent 所指定的View */ public void showAsDropDown(View parent) { mPopupWindow.showAsDropDown(parent); } /** * 隱藏菜單. */ public void dismiss() { mPopupWindow.dismiss(); } /** * 設置菜單選擇監聽. * * @param listener 監聽器. */ public void setOnItemSelectedListener(OnItemSelectedListener listener) { mListener = listener; } /** * 當前菜單是否正在顯示. * * @return */ public boolean isShowing() { return mPopupWindow.isShowing(); } /** * 菜單項. */ public static class Item { public String text; public int id; public Item(String text, int id) { this.text = text; this.id = id; } @Override public String toString() { return text; } } /** * 菜單項選擇監聽接口. */ public static interface OnItemSelectedListener { /** * 菜單被選擇時的回調接口. * * @param view 被選擇的內容的View. * @param item 被選擇的菜單項. * @param position 被選擇的位置. */ public void selected(View view, Item item, int position); } }
第二個方法是findListView(View view)。這是因為我們的菜單通常是一個列表,然後點擊去選擇列表的某一項,所以這裡需要返回一個ListView對象,用來裝載我們的菜單項。
第三個方法是onCreateAdapter,即listview的適配器。
在這個類中,還封裝了一個內部類Item:
/** * 菜單項. */ public static class Item { public String text; public int id; public Item(String text, int id) { this.text = text; this.id = id; } @Override public String toString() { return text; } }它用來表示我們的菜單項,text是顯示在菜單當中的文本信息,id表示菜單項的ID。
在該抽象類中還定義了一個接口OnItemSelectedListener,是在菜單項被點擊時的回調接口。關於它的說明見注釋,這是我在這個博客裡目前為止注釋寫得最詳細的一個類了。
首先繼承PopMenu並實現抽象方法:
/* * Date: 14-9-2 * Project: Access-Control-V2 */ package cn.irains.access.v2.usermanager; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import java.util.ArrayList; import cn.irains.access.v2.R; import cn.irains.access.v2.common.PopMenu; /** * Author: msdx ([email protected]) * Time: 14-9-2 上午8:56 */ public class UserMenu extends PopMenu { public UserMenu(Context context) { super(context); } @Override protected ListView findListView(View view) { return (ListView) view.findViewById(R.id.menu_listview); } @Override protected View onCreateView(Context context) { View view = LayoutInflater.from(context).inflate(R.layout.menu_user, null); return view; } @Override protected ArrayAdapter- onCreateAdapter(Context context, ArrayList
- items) { return new ArrayAdapter
- (context, R.layout.item_menu_user, items); } }
/* * Date: 14-9-2 * Project: Access-Control-V2 */ package cn.irains.access.v2.common; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.ListView; /** * 寬度適配內容的ListView. * Author: msdx ([email protected]) * Time: 14-9-2 下午5:14 */ public class WrapWidthListView extends ListView { public WrapWidthListView(Context context) { super(context); } public WrapWidthListView(Context context, AttributeSet attrs) { super(context, attrs); } public WrapWidthListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec); int w = child.getMeasuredWidth(); if (w > width) width = w; } widthMeasureSpec = MeasureSpec.makeMeasureSpec(width + getPaddingLeft() + getPaddingRight(), MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
其中的ImageView的照片是一個黑色三角圖案。這個等在最後我發一下效果圖就明白了。ListView背景是一張黑色圖片。
接下來是item的布局,只是一個TextView,代碼如下:
private static final int USER_SEARCH = 0; private static final int USER_ADD = 1; private UserMenu mMenu; private void initMenu() { mMenu = new UserMenu(context); mMenu.addItem(R.string.user_search, USER_SEARCH); mMenu.addItem(R.string.user_add, USER_ADD); mMenu.setOnItemSelectedListener(new PopMenu.OnItemSelectedListener() { @Override public void selected(View view, PopMenu.Item item, int position) { switch (item.id) { case USER_SEARCH: startActivity(new Intent(getActivity(), UserSearchActivity.class)); break; case USER_ADD: startActivity(new Intent(getActivity(), UserAddActivity.class)); break; } } }); }在activity的onCreate或fragment中的onCreateView中初始化menu代碼,然後需要顯示時調用mMenu.showAsDropDown(view);它就作為view的下拉菜單顯示了。效果如下:
android中提供了4中動畫: AlphaAnimation 透明度動畫效果 ScaleAnimation 縮放動畫效果 TranslateAnimation 位移動畫
通常我們在使用key-value存儲數據時,隨手就會打出HashMap的代碼,當數據量較小時,還可以,當數量比較多的時候,如果是PC機上,也還說得過去,但是如果使用設備是
本例主要實現在APP中解析GML數據並顯示GML,地理標記語言(外語全稱:Geography MarkupLanguage、外語縮寫:GML),它由開放式地理信息系統協會
主要的類: package de.hdodenhof.circleimageview; import edu.njupt.zhb.main.