編輯:關於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 (645079761@qq.com)
* 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 (645079761@qq.com)
* 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 (645079761@qq.com)
* 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 動畫之ScaleAnimation應用詳解
android中提供了4中動畫: AlphaAnimation 透明度動畫效果 ScaleAnimation 縮放動畫效果 TranslateAnimation 位移動畫
Android內存優化:ArrayMap
通常我們在使用key-value存儲數據時,隨手就會打出HashMap的代碼,當數據量較小時,還可以,當數量比較多的時候,如果是PC機上,也還說得過去,但是如果使用設備是
Android之解析GML並顯示
本例主要實現在APP中解析GML數據並顯示GML,地理標記語言(外語全稱:Geography MarkupLanguage、外語縮寫:GML),它由開放式地理信息系統協會
android開源系列:CircleImageView自定義圓形控件的使用
主要的類: package de.hdodenhof.circleimageview; import edu.njupt.zhb.main.