原文:http://xyzlmn.blog.51cto.com/2532390/817276
PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。
实现中使用的 PopupWindow。这里做了简单封装,其中有三个类组成:PopuItem、PopuJar、PopupWindows。
- public class PopuItem {
- private Drawable icon;
- private Bitmap thumb;
- private String title;
- private int actionId = -1;
- private boolean selected;
- private boolean sticky;
- /**
- * Constructor
- *
- * @param actionId Action id for case statements
- * @param title Title
- * @param icon Icon to use
- */
- public PopuItem(int actionId, String title, Drawable icon) {
- this.title = title;
- this.icon = icon;
- this.actionId = actionId;
- }
- /**
- * Constructor
- */
- public PopuItem() {
- this(-1, null, null);
- }
- /**
- * Constructor
- *
- * @param actionId Action id of the item
- * @param title Text to show for the item
- */
- public PopuItem(int actionId, String title) {
- this(actionId, title, null);
- }
- /**
- * Constructor
- *
- * @param icon [email protected] Drawable} action icon
- */
- public PopuItem(Drawable icon) {
- this(-1, null, icon);
- }
- /**
- * Constructor
- *
- * @param actionId Action ID of item
- * @param icon [email protected] Drawable} action icon
- */
- public PopuItem(int actionId, Drawable icon) {
- this(actionId, null, icon);
- }
- /**
- * Set action title
- *
- * @param title action title
- */
- public void setTitle(String title) {
- this.title = title;
- }
- /**
- * Get action title
- *
- * @return action title
- */
- public String getTitle() {
- return this.title;
- }
- /**
- * Set action icon
- *
- * @param icon [email protected] Drawable} action icon
- */
- public void setIcon(Drawable icon) {
- this.icon = icon;
- }
- /**
- * Get action icon
- * @return [email protected] Drawable} action icon
- */
- public Drawable getIcon() {
- return this.icon;
- }
- /**
- * Set action id
- *
- * @param actionId Action id for this action
- */
- public void setActionId(int actionId) {
- this.actionId = actionId;
- }
- /**
- * @return Our action id
- */
- public int getActionId() {
- return actionId;
- }
- /**
- * Set sticky status of button
- *
- * @param sticky true for sticky, pop up sends event but does not disappear
- */
- public void setSticky(boolean sticky) {
- this.sticky = sticky;
- }
- /**
- * @return true if button is sticky, menu stays visible after press
- */
- public boolean isSticky() {
- return sticky;
- }
- /**
- * Set selected flag;
- *
- * @param selected Flag to indicate the item is selected
- */
- public void setSelected(boolean selected) {
- this.selected = selected;
- }
- /**
- * Check if item is selected
- *
- * @return true or false
- */
- public boolean isSelected() {
- return this.selected;
- }
- /**
- * Set thumb
- *
- * @param thumb Thumb image
- */
- public void setThumb(Bitmap thumb) {
- this.thumb = thumb;
- }
- /**
- * Get thumb image
- *
- * @return Thumb image
- */
- public Bitmap getThumb() {
- return this.thumb;
- }
- }
- public class PopuJar extends PopupWindows implements OnDismissListener {
- private View mRootView;
- private ImageView mArrowUp;
- private ImageView mArrowDown;
- private LayoutInflater mInflater;
- private ViewGroup mTrack;
- private ScrollView mScroller;
- private OnPopuItemClickListener mItemClickListener;
- private OnDismissListener mDismissListener;
- private List<PopuItem> PopuItems = new ArrayList<PopuItem>();
- private boolean mDidAction;
- private int mChildPos;
- private int mInsertPos;
- private int mAnimStyle;
- private int mOrientation;
- private int rootWidth=0;
- public static final int HORIZONTAL = 0;
- public static final int VERTICAL = 1;
- public static final int ANIM_GROW_FROM_LEFT = 1;
- public static final int ANIM_GROW_FROM_RIGHT = 2;
- public static final int ANIM_GROW_FROM_CENTER = 3;
- public static final int ANIM_REFLECT = 4;
- public static final int ANIM_AUTO = 5;
- /**
- * Constructor for default vertical layout
- *
- * @param context Context
- */
- public PopuJar(Context context) {
- this(context, VERTICAL);
- }
- /**
- * Constructor allowing orientation override
- *
- * @param context Context
- * @param orientation Layout orientation, can be vartical or horizontal
- */
- public PopuJar(Context context, int orientation) {
- super(context);
- mOrientation = orientation;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (mOrientation == HORIZONTAL) {
- setRootViewId(R.layout.popup_horizontal);
- } else {
- setRootViewId(R.layout.popup_vertical);
- }
- mAnimStyle = ANIM_AUTO;
- mChildPos = 0;
- }
- /**
- * Get action item at an index
- *
- * @param index Index of item (position from callback)
- *
- * @return Action Item at the position
- */
- public PopuItem getPopuItem(int index) {
- return PopuItems.get(index);
- }
- /**
- * Set root view.
- *
- * @param id Layout resource id
- */
- public void setRootViewId(int id) {
- mRootView = (ViewGroup) mInflater.inflate(id, null);
- mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks);
- mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down);
- mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up);
- mScroller = (ScrollView) mRootView.findViewById(R.id.scroller);
- //This was previously defined on show() method, moved here to prevent force close that occured
- //when tapping fastly on a view to show quickaction dialog.
- //Thanx to zammbi (github.com/zammbi)
- mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- setContentView(mRootView);
- }
- /**
- * Set animation style
- *
- * @param mAnimStyle animation style, default is set to ANIM_AUTO
- */
- public void setAnimStyle(int mAnimStyle) {
- this.mAnimStyle = mAnimStyle;
- }
- /**
- * Set listener for action item clicked.
- *
- * @param listener Listener
- */
- public void setOnPopuItemClickListener(OnPopuItemClickListener listener) {
- mItemClickListener = listener;
- }
- /**
- * Add action item
- *
- * @param action [email protected] PopuItem}
- */
- public void addPopuItem(PopuItem action) {
- PopuItems.add(action);
- String title = action.getTitle();
- Drawable icon = action.getIcon();
- View container;
- if (mOrientation == HORIZONTAL) {
- container = mInflater.inflate(R.layout.action_item_horizontal, null);
- } else {
- container = mInflater.inflate(R.layout.action_item_vertical, null);
- }
- ImageView img = (ImageView) container.findViewById(R.id.iv_icon);
- TextView text = (TextView) container.findViewById(R.id.tv_title);
- if (icon != null) {
- img.setImageDrawable(icon);
- } else {
- img.setVisibility(View.GONE);
- }
- if (title != null) {
- text.setText(title);
- } else {
- text.setVisibility(View.GONE);
- }
- final int pos = mChildPos;
- final int actionId = action.getActionId();
- container.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mItemClickListener != null) {
- mItemClickListener.onItemClick(PopuJar.this, pos, actionId);
- }
- if (!getPopuItem(pos).isSticky()) {
- mDidAction = true;
- dismiss();
- }
- }
- });
- container.setFocusable(true);
- container.setClickable(true);
- if (mOrientation == HORIZONTAL && mChildPos != 0) {
- View separator = mInflater.inflate(R.layout.horiz_separator, null);
- RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
- separator.setLayoutParams(params);
- separator.setPadding(5, 0, 5, 0);
- mTrack.addView(separator, mInsertPos);
- mInsertPos++;
- }
- mTrack.addView(container, mInsertPos);
- mChildPos++;
- mInsertPos++;
- }
- /**
- * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view.
- *
- */
- public void show (View anchor) {
- preShow();
- int xPos, yPos, arrowPos;
- mDidAction = false;
- int[] location = new int[2];
- anchor.getLocationOnScreen(location);
- Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
- + anchor.getHeight());
- //mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- int rootHeight = mRootView.getMeasuredHeight();
- if (rootWidth == 0) {
- rootWidth = mRootView.getMeasuredWidth();
- }
- int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
- int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
- //automatically get X coord of popup (top left)
- if ((anchorRect.left + rootWidth) > screenWidth) {
- xPos = anchorRect.left - (rootWidth-anchor.getWidth());
- xPos = (xPos < 0) ? 0 : xPos;
- arrowPos = anchorRect.centerX()-xPos;
- } else {
- if (anchor.getWidth() > rootWidth) {
- xPos = anchorRect.centerX() - (rootWidth/2);
- } else {
- xPos = anchorRect.left;
- }
- arrowPos = anchorRect.centerX()-xPos;
- }
- int dyTop = anchorRect.top;
- int dyBottom = screenHeight - anchorRect.bottom;
- boolean onTop = (dyTop > dyBottom) ? true : false;
- if (onTop) {
- if (rootHeight > dyTop) {
- yPos = 15;
- LayoutParams l = mScroller.getLayoutParams();
- l.height = dyTop - anchor.getHeight();
- } else {
- yPos = anchorRect.top - rootHeight;
- }
- } else {
- yPos = anchorRect.bottom;
- if (rootHeight > dyBottom) {
- LayoutParams l = mScroller.getLayoutParams();
- l.height = dyBottom;
- }
- }
- showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
- setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
- mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
- }
- /**
- * Set animation style
- *
- * @param screenWidth screen width
- * @param requestedX distance from left edge
- * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view
- * and vice versa
- */
- private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
- int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
- switch (mAnimStyle) {
- case ANIM_GROW_FROM_LEFT:
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
- break;
- case ANIM_GROW_FROM_RIGHT:
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
- break;
- case ANIM_GROW_FROM_CENTER:
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
- break;
- case ANIM_REFLECT:
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);
- break;
- case ANIM_AUTO:
- if (arrowPos <= screenWidth/4) {
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
- } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
- } else {
- mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
- }
- break;
- }
- }
- /**
- * Show arrow
- *
- * @param whichArrow arrow type resource id
- * @param requestedX distance from left screen
- */
- private void showArrow(int whichArrow, int requestedX) {
- final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
- final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
- final int arrowWidth = mArrowUp.getMeasuredWidth();
- showArrow.setVisibility(View.VISIBLE);
- ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
- param.leftMargin = requestedX - arrowWidth / 2;
- hideArrow.setVisibility(View.INVISIBLE);
- }
- /**
- * Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed
- * by clicking outside the dialog or clicking on sticky item.
- */
- public void setOnDismissListener(PopuJar.OnDismissListener listener) {
- setOnDismissListener(this);
- mDismissListener = listener;
- }
- @Override
- public void onDismiss() {
- if (!mDidAction && mDismissListener != null) {
- mDismissListener.onDismiss();
- }
- }
- /**
- * Listener for item click
- *
- */
- public interface OnPopuItemClickListener {
- public abstract void onItemClick(PopuJar source, int pos, int actionId);
- }
- /**
- * Listener for window dismiss
- *
- */
- public interface OnDismissListener {
- public abstract void onDismiss();
- }
- }
- public class PopupWindows {
- protected Context mContext;
- protected PopupWindow mWindow;
- protected View mRootView;
- protected Drawable mBackground = null;
- protected WindowManager mWindowManager;
- /**
- * Constructor.
- *
- * @param context Context
- */
- public PopupWindows(Context context) {
- mContext = context;
- mWindow = new PopupWindow(context);
- mWindow.setTouchInterceptor(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- mWindow.dismiss();
- return true;
- }
- return false;
- }
- });
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
- /**
- * On dismiss
- */
- protected void onDismiss() {
- }
- /**
- * On show
- */
- protected void onShow() {
- }
- /**
- * On pre show
- */
- protected void preShow() {
- if (mRootView == null)
- throw new IllegalStateException("setContentView was not called with a view to display.");
- onShow();
- if (mBackground == null)
- mWindow.setBackgroundDrawable(new BitmapDrawable());
- else
- mWindow.setBackgroundDrawable(mBackground);
- mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
- mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
- mWindow.setTouchable(true);
- mWindow.setFocusable(true);
- mWindow.setOutsideTouchable(true);
- mWindow.setContentView(mRootView);
- }
- /**
- * Set background drawable.
- *
- * @param background Background drawable
- */
- public void setBackgroundDrawable(Drawable background) {
- mBackground = background;
- }
- /**
- * Set content view.
- *
- * @param root Root view
- */
- public void setContentView(View root) {
- mRootView = root;
- mWindow.setContentView(root);
- }
- /**
- * Set content view.
- *
- * @param layoutResID Resource id
- */
- public void setContentView(int layoutResID) {
- LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- setContentView(inflator.inflate(layoutResID, null));
- }
- /**
- * Set listener on window dismissed.
- *
- * @param listener
- */
- public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
- mWindow.setOnDismissListener(listener);
- }
- /**
- * Dismiss the popup window.
- */
- public void dismiss() {
- mWindow.dismiss();
- }
- }
显示popu:
参考:
http://code.google.com/p/simple-quickactions/