package com.nix.ui.widget.popupmenu; import com.nix.sample.R; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.View.MeasureSpec; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.FrameLayout; import android.widget.ListAdapter; import android.widget.PopupWindow; /** * @author niexinxin: * @date 2013-5-16 * @version 1.0 */ public class PopupMenu implements AdapterView.OnItemClickListener, View.OnKeyListener, ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener { private final static String TAG = PopupMenu.class.getSimpleName(); private Context mContext; private BaseAdapter mMenuAdapter; private IcsListPopupWindow mPopup; private View mAnchorView; private ViewGroup mMeasureParent; private Drawable mBgDrawable; private ViewTreeObserver mTreeObserver; private int mPopupMaxWidth; private int mScreenWidth; private boolean mIsForceBelowAnchor = false; private AdapterView.OnItemClickListener mOnItemClickListener; public PopupMenu(Context context) { this(context, null); } public PopupMenu(Context context, View anchorView) { mContext = context; mScreenWidth = context.getResources().getDisplayMetrics().widthPixels; mPopupMaxWidth = mScreenWidth / 2; mAnchorView = anchorView; mBgDrawable = context.getResources().getDrawable( R.drawable.default_menu_panel_background); } public void setAnchorView(View anchor) { mAnchorView = anchor; } public void setAdapter(BaseAdapter adapter) { mMenuAdapter = adapter; } public void setBackground(Drawable bgDrawable) { if (bgDrawable != null) { mBgDrawable = bgDrawable; } } public void setPopupMaxWidth(int maxWidth) { if (maxWidth > 0 && maxWidth < mScreenWidth) { mPopupMaxWidth = maxWidth; } } public void setOnItemClickListener( AdapterView.OnItemClickListener onItemClickListener) { mOnItemClickListener = onItemClickListener; } public boolean tryShow() { // mPopup = new IcsListPopupWindow(mContext, null, // R.attr.popupMenuStyle); mPopup = new IcsListPopupWindow(mContext, null, 0); mPopup.setOnDismissListener(this); mPopup.setOnItemClickListener(this); mPopup.setBackgroundDrawable(mBgDrawable); mPopup.setAdapter(mMenuAdapter); mPopup.setModal(true); View anchor = mAnchorView; if (anchor != null) { final boolean addGlobalListener = mTreeObserver == null; mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest if (addGlobalListener) { mTreeObserver.addOnGlobalLayoutListener(this); } mPopup.setAnchorView(anchor); } else { return false; } mPopup.setContentWidth(Math.min(measureContentWidth(mMenuAdapter), mPopupMaxWidth)); if(mIsForceBelowAnchor){ mPopup.setMaxHeight(measureLeftHight()); } mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); mPopup.show(); mPopup.getListView().setOnKeyListener(this); return true; } public void setForceBelowAnchor(boolean force){ mIsForceBelowAnchor = force; } private int measureLeftHight() { int viewBootom = mAnchorView.getBottom(); int screenHeight = mContext.getResources().getDisplayMetrics().heightPixels; Rect rect = new Rect(); mAnchorView.getGlobalVisibleRect(rect); Log.d(TAG, "viewBootom = " + viewBootom); Log.d(TAG, "rect.bottom = " + rect.bottom); Log.d(TAG, "screenHeight =" + screenHeight); Log.d(TAG, "screenHeight - rect.bottom =" + (screenHeight - rect.bottom)); return screenHeight - rect.bottom; } private int measureContentWidth(ListAdapter adapter) { // Menus don't tend to be long, so this is more sane than it looks. int width = 0; View itemView = null; int itemType = 0; final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); final int count = adapter.getCount(); for (int i = 0; i < count; i++) { final int positionType = adapter.getItemViewType(i); if (positionType != itemType) { itemType = positionType; itemView = null; } if (mMeasureParent == null) { mMeasureParent = new FrameLayout(mContext); } itemView = adapter.getView(i, itemView, mMeasureParent); itemView.measure(widthMeasureSpec, heightMeasureSpec); width = Math.max(width, itemView.getMeasuredWidth()); } return width; } public void dismiss() { if (isShowing()) { mPopup.dismiss(); } } @SuppressWarnings("deprecation") public void onDismiss() { mPopup = null; if (mTreeObserver != null) { if (!mTreeObserver.isAlive()) { mTreeObserver = mAnchorView.getViewTreeObserver(); } mTreeObserver.removeGlobalOnLayoutListener(this); mTreeObserver = null; } } public boolean isShowing() { return mPopup != null && mPopup.isShowing(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { dismiss(); if (mOnItemClickListener != null) { mOnItemClickListener.onItemClick(parent, view, position, id); } } public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { dismiss(); return true; } return false; } @Override public void onGlobalLayout() { if (isShowing()) { final View anchor = mAnchorView; if (anchor == null || !anchor.isShown()) { dismiss(); } else if (isShowing()) { // Recompute window size and position mPopup.show(); } } } }