UI开发第十六篇——分享一个popuwindow实例

来源:互联网 发布:c语言中>> 编辑:程序博客网 时间:2024/06/04 20:08
       PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。

UI开发第三篇——popupwindow 中简单介绍了一些简单方法,这一篇分享一个实例。看效果:

             

 

 

     

 

实现中使用的  PopupWindow。这里做了简单封装,其中有三个类组成:PopuItem、PopuJar、PopupWindows。

view plain
  1. public class PopuItem {  
  2.     private Drawable icon;  
  3.     private Bitmap thumb;  
  4.     private String title;  
  5.     private int actionId = -1;  
  6.     private boolean selected;  
  7.     private boolean sticky;  
  8.       
  9.     /** 
  10.      * Constructor 
  11.      *  
  12.      * @param actionId  Action id for case statements 
  13.      * @param title     Title 
  14.      * @param icon      Icon to use 
  15.      */  
  16.     public PopuItem(int actionId, String title, Drawable icon) {  
  17.         this.title = title;  
  18.         this.icon = icon;  
  19.         this.actionId = actionId;  
  20.     }  
  21.       
  22.     /** 
  23.      * Constructor 
  24.      */  
  25.     public PopuItem() {  
  26.         this(-1nullnull);  
  27.     }  
  28.       
  29.     /** 
  30.      * Constructor 
  31.      *  
  32.      * @param actionId  Action id of the item 
  33.      * @param title     Text to show for the item 
  34.      */  
  35.     public PopuItem(int actionId, String title) {  
  36.         this(actionId, title, null);  
  37.     }  
  38.       
  39.     /** 
  40.      * Constructor 
  41.      *  
  42.      * @param icon {@link Drawable} action icon 
  43.      */  
  44.     public PopuItem(Drawable icon) {  
  45.         this(-1null, icon);  
  46.     }  
  47.       
  48.     /** 
  49.      * Constructor 
  50.      *  
  51.      * @param actionId  Action ID of item 
  52.      * @param icon      {@link Drawable} action icon 
  53.      */  
  54.     public PopuItem(int actionId, Drawable icon) {  
  55.         this(actionId, null, icon);  
  56.     }  
  57.       
  58.     /** 
  59.      * Set action title 
  60.      *  
  61.      * @param title action title 
  62.      */  
  63.     public void setTitle(String title) {  
  64.         this.title = title;  
  65.     }  
  66.       
  67.     /** 
  68.      * Get action title 
  69.      *  
  70.      * @return action title 
  71.      */  
  72.     public String getTitle() {  
  73.         return this.title;  
  74.     }  
  75.       
  76.     /** 
  77.      * Set action icon 
  78.      *  
  79.      * @param icon {@link Drawable} action icon 
  80.      */  
  81.     public void setIcon(Drawable icon) {  
  82.         this.icon = icon;  
  83.     }  
  84.       
  85.     /** 
  86.      * Get action icon 
  87.      * @return  {@link Drawable} action icon 
  88.      */  
  89.     public Drawable getIcon() {  
  90.         return this.icon;  
  91.     }  
  92.       
  93.      /** 
  94.      * Set action id 
  95.      *  
  96.      * @param actionId  Action id for this action 
  97.      */  
  98.     public void setActionId(int actionId) {  
  99.         this.actionId = actionId;  
  100.     }  
  101.       
  102.     /** 
  103.      * @return  Our action id 
  104.      */  
  105.     public int getActionId() {  
  106.         return actionId;  
  107.     }  
  108.       
  109.     /** 
  110.      * Set sticky status of button 
  111.      *  
  112.      * @param sticky  true for sticky, pop up sends event but does not disappear 
  113.      */  
  114.     public void setSticky(boolean sticky) {  
  115.         this.sticky = sticky;  
  116.     }  
  117.       
  118.     /** 
  119.      * @return  true if button is sticky, menu stays visible after press 
  120.      */  
  121.     public boolean isSticky() {  
  122.         return sticky;  
  123.     }  
  124.       
  125.     /** 
  126.      * Set selected flag; 
  127.      *  
  128.      * @param selected Flag to indicate the item is selected 
  129.      */  
  130.     public void setSelected(boolean selected) {  
  131.         this.selected = selected;  
  132.     }  
  133.       
  134.     /** 
  135.      * Check if item is selected 
  136.      *  
  137.      * @return true or false 
  138.      */  
  139.     public boolean isSelected() {  
  140.         return this.selected;  
  141.     }  
  142.   
  143.     /** 
  144.      * Set thumb 
  145.      *  
  146.      * @param thumb Thumb image 
  147.      */  
  148.     public void setThumb(Bitmap thumb) {  
  149.         this.thumb = thumb;  
  150.     }  
  151.       
  152.     /** 
  153.      * Get thumb image 
  154.      *  
  155.      * @return Thumb image 
  156.      */  
  157.     public Bitmap getThumb() {  
  158.         return this.thumb;  
  159.     }  
  160. }  


 

view plain
  1. public class PopuJar extends PopupWindows implements OnDismissListener {  
  2.     private View mRootView;  
  3.     private ImageView mArrowUp;  
  4.     private ImageView mArrowDown;  
  5.     private LayoutInflater mInflater;  
  6.     private ViewGroup mTrack;  
  7.     private ScrollView mScroller;  
  8.     private OnPopuItemClickListener mItemClickListener;  
  9.     private OnDismissListener mDismissListener;  
  10.       
  11.     private List<PopuItem> PopuItems = new ArrayList<PopuItem>();  
  12.       
  13.     private boolean mDidAction;  
  14.       
  15.     private int mChildPos;  
  16.     private int mInsertPos;  
  17.     private int mAnimStyle;  
  18.     private int mOrientation;  
  19.     private int rootWidth=0;  
  20.       
  21.     public static final int HORIZONTAL = 0;  
  22.     public static final int VERTICAL = 1;  
  23.       
  24.     public static final int ANIM_GROW_FROM_LEFT = 1;  
  25.     public static final int ANIM_GROW_FROM_RIGHT = 2;  
  26.     public static final int ANIM_GROW_FROM_CENTER = 3;  
  27.     public static final int ANIM_REFLECT = 4;  
  28.     public static final int ANIM_AUTO = 5;  
  29.       
  30.     /** 
  31.      * Constructor for default vertical layout 
  32.      *  
  33.      * @param context  Context 
  34.      */  
  35.     public PopuJar(Context context) {  
  36.         this(context, VERTICAL);  
  37.     }  
  38.   
  39.     /** 
  40.      * Constructor allowing orientation override 
  41.      *  
  42.      * @param context    Context 
  43.      * @param orientation Layout orientation, can be vartical or horizontal 
  44.      */  
  45.     public PopuJar(Context context, int orientation) {  
  46.         super(context);  
  47.           
  48.         mOrientation = orientation;  
  49.           
  50.         mInflater    = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  51.   
  52.         if (mOrientation == HORIZONTAL) {  
  53.             setRootViewId(R.layout.popup_horizontal);  
  54.         } else {  
  55.             setRootViewId(R.layout.popup_vertical);  
  56.         }  
  57.   
  58.         mAnimStyle  = ANIM_AUTO;  
  59.         mChildPos   = 0;  
  60.     }  
  61.   
  62.     /** 
  63.      * Get action item at an index 
  64.      *  
  65.      * @param index  Index of item (position from callback) 
  66.      *  
  67.      * @return  Action Item at the position 
  68.      */  
  69.     public PopuItem getPopuItem(int index) {  
  70.         return PopuItems.get(index);  
  71.     }  
  72.       
  73.     /** 
  74.      * Set root view. 
  75.      *  
  76.      * @param id Layout resource id 
  77.      */  
  78.     public void setRootViewId(int id) {  
  79.         mRootView   = (ViewGroup) mInflater.inflate(id, null);  
  80.         mTrack      = (ViewGroup) mRootView.findViewById(R.id.tracks);  
  81.   
  82.         mArrowDown  = (ImageView) mRootView.findViewById(R.id.arrow_down);  
  83.         mArrowUp    = (ImageView) mRootView.findViewById(R.id.arrow_up);  
  84.   
  85.         mScroller   = (ScrollView) mRootView.findViewById(R.id.scroller);  
  86.           
  87.         //This was previously defined on show() method, moved here to prevent force close that occured  
  88.         //when tapping fastly on a view to show quickaction dialog.  
  89.         //Thanx to zammbi (github.com/zammbi)  
  90.         mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
  91.           
  92.         setContentView(mRootView);  
  93.     }  
  94.       
  95.     /** 
  96.      * Set animation style 
  97.      *  
  98.      * @param mAnimStyle animation style, default is set to ANIM_AUTO 
  99.      */  
  100.     public void setAnimStyle(int mAnimStyle) {  
  101.         this.mAnimStyle = mAnimStyle;  
  102.     }  
  103.       
  104.     /** 
  105.      * Set listener for action item clicked. 
  106.      *  
  107.      * @param listener Listener 
  108.      */  
  109.     public void setOnPopuItemClickListener(OnPopuItemClickListener listener) {  
  110.         mItemClickListener = listener;  
  111.     }  
  112.       
  113.     /** 
  114.      * Add action item 
  115.      *  
  116.      * @param action  {@link PopuItem} 
  117.      */  
  118.     public void addPopuItem(PopuItem action) {  
  119.         PopuItems.add(action);  
  120.           
  121.         String title    = action.getTitle();  
  122.         Drawable icon   = action.getIcon();  
  123.           
  124.         View container;  
  125.           
  126.         if (mOrientation == HORIZONTAL) {  
  127.             container = mInflater.inflate(R.layout.action_item_horizontal, null);  
  128.         } else {  
  129.             container = mInflater.inflate(R.layout.action_item_vertical, null);  
  130.         }  
  131.           
  132.         ImageView img   = (ImageView) container.findViewById(R.id.iv_icon);  
  133.         TextView text   = (TextView) container.findViewById(R.id.tv_title);  
  134.           
  135.         if (icon != null) {  
  136.             img.setImageDrawable(icon);  
  137.         } else {  
  138.             img.setVisibility(View.GONE);  
  139.         }  
  140.           
  141.         if (title != null) {  
  142.             text.setText(title);  
  143.         } else {  
  144.             text.setVisibility(View.GONE);  
  145.         }  
  146.           
  147.         final int pos       =  mChildPos;  
  148.         final int actionId  = action.getActionId();  
  149.           
  150.         container.setOnClickListener(new OnClickListener() {  
  151.             @Override  
  152.             public void onClick(View v) {  
  153.                 if (mItemClickListener != null) {  
  154.                     mItemClickListener.onItemClick(PopuJar.this, pos, actionId);  
  155.                 }  
  156.                   
  157.                 if (!getPopuItem(pos).isSticky()) {    
  158.                     mDidAction = true;  
  159.                       
  160.                     dismiss();  
  161.                 }  
  162.             }  
  163.         });  
  164.           
  165.         container.setFocusable(true);  
  166.         container.setClickable(true);  
  167.                
  168.         if (mOrientation == HORIZONTAL && mChildPos != 0) {  
  169.             View separator = mInflater.inflate(R.layout.horiz_separator, null);  
  170.               
  171.             RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);  
  172.               
  173.             separator.setLayoutParams(params);  
  174.             separator.setPadding(5050);  
  175.               
  176.             mTrack.addView(separator, mInsertPos);  
  177.               
  178.             mInsertPos++;  
  179.         }  
  180.           
  181.         mTrack.addView(container, mInsertPos);  
  182.           
  183.         mChildPos++;  
  184.         mInsertPos++;  
  185.     }  
  186.       
  187.     /** 
  188.      * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view. 
  189.      *  
  190.      */  
  191.     public void show (View anchor) {  
  192.         preShow();  
  193.           
  194.         int xPos, yPos, arrowPos;  
  195.           
  196.         mDidAction          = false;  
  197.           
  198.         int[] location      = new int[2];  
  199.       
  200.         anchor.getLocationOnScreen(location);  
  201.   
  202.         Rect anchorRect     = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]   
  203.                             + anchor.getHeight());  
  204.   
  205.         //mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
  206.           
  207.         mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
  208.       
  209.         int rootHeight      = mRootView.getMeasuredHeight();  
  210.           
  211.         if (rootWidth == 0) {  
  212.             rootWidth       = mRootView.getMeasuredWidth();  
  213.         }  
  214.           
  215.         int screenWidth     = mWindowManager.getDefaultDisplay().getWidth();  
  216.         int screenHeight    = mWindowManager.getDefaultDisplay().getHeight();  
  217.           
  218.         //automatically get X coord of popup (top left)  
  219.         if ((anchorRect.left + rootWidth) > screenWidth) {  
  220.             xPos        = anchorRect.left - (rootWidth-anchor.getWidth());            
  221.             xPos        = (xPos < 0) ? 0 : xPos;  
  222.               
  223.             arrowPos    = anchorRect.centerX()-xPos;  
  224.               
  225.         } else {  
  226.             if (anchor.getWidth() > rootWidth) {  
  227.                 xPos = anchorRect.centerX() - (rootWidth/2);  
  228.             } else {  
  229.                 xPos = anchorRect.left;  
  230.             }  
  231.               
  232.             arrowPos = anchorRect.centerX()-xPos;  
  233.         }  
  234.           
  235.         int dyTop           = anchorRect.top;  
  236.         int dyBottom        = screenHeight - anchorRect.bottom;  
  237.   
  238.         boolean onTop       = (dyTop > dyBottom) ? true : false;  
  239.   
  240.         if (onTop) {  
  241.             if (rootHeight > dyTop) {  
  242.                 yPos            = 15;  
  243.                 LayoutParams l  = mScroller.getLayoutParams();  
  244.                 l.height        = dyTop - anchor.getHeight();  
  245.             } else {  
  246.                 yPos = anchorRect.top - rootHeight;  
  247.             }  
  248.         } else {  
  249.             yPos = anchorRect.bottom;  
  250.               
  251.             if (rootHeight > dyBottom) {   
  252.                 LayoutParams l  = mScroller.getLayoutParams();  
  253.                 l.height        = dyBottom;  
  254.             }  
  255.         }  
  256.           
  257.         showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);  
  258.           
  259.         setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);  
  260.           
  261.         mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);  
  262.     }  
  263.       
  264.     /** 
  265.      * Set animation style 
  266.      *  
  267.      * @param screenWidth screen width 
  268.      * @param requestedX distance from left edge 
  269.      * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view 
  270.      *        and vice versa 
  271.      */  
  272.     private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {  
  273.         int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;  
  274.   
  275.         switch (mAnimStyle) {  
  276.         case ANIM_GROW_FROM_LEFT:  
  277.             mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);  
  278.             break;  
  279.                       
  280.         case ANIM_GROW_FROM_RIGHT:  
  281.             mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);  
  282.             break;  
  283.                       
  284.         case ANIM_GROW_FROM_CENTER:  
  285.             mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);  
  286.         break;  
  287.               
  288.         case ANIM_REFLECT:  
  289.             mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);  
  290.         break;  
  291.           
  292.         case ANIM_AUTO:  
  293.             if (arrowPos <= screenWidth/4) {  
  294.                 mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);  
  295.             } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {  
  296.                 mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);  
  297.             } else {  
  298.                 mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);  
  299.             }  
  300.                       
  301.             break;  
  302.         }  
  303.     }  
  304.       
  305.     /** 
  306.      * Show arrow 
  307.      *  
  308.      * @param whichArrow arrow type resource id 
  309.      * @param requestedX distance from left screen 
  310.      */  
  311.     private void showArrow(int whichArrow, int requestedX) {  
  312.         final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;  
  313.         final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;  
  314.   
  315.         final int arrowWidth = mArrowUp.getMeasuredWidth();  
  316.   
  317.         showArrow.setVisibility(View.VISIBLE);  
  318.           
  319.         ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();  
  320.          
  321.         param.leftMargin = requestedX - arrowWidth / 2;  
  322.           
  323.         hideArrow.setVisibility(View.INVISIBLE);  
  324.     }  
  325.       
  326.     /** 
  327.      * Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed 
  328.      * by clicking outside the dialog or clicking on sticky item. 
  329.      */  
  330.     public void setOnDismissListener(PopuJar.OnDismissListener listener) {  
  331.         setOnDismissListener(this);  
  332.           
  333.         mDismissListener = listener;  
  334.     }  
  335.       
  336.     @Override  
  337.     public void onDismiss() {  
  338.         if (!mDidAction && mDismissListener != null) {  
  339.             mDismissListener.onDismiss();  
  340.         }  
  341.     }  
  342.       
  343.     /** 
  344.      * Listener for item click 
  345.      * 
  346.      */  
  347.     public interface OnPopuItemClickListener {  
  348.         public abstract void onItemClick(PopuJar source, int pos, int actionId);  
  349.     }  
  350.       
  351.     /** 
  352.      * Listener for window dismiss 
  353.      *  
  354.      */  
  355.     public interface OnDismissListener {  
  356.         public abstract void onDismiss();  
  357.     }  
  358. }  


 

 

view plain
  1. public class PopupWindows {  
  2.     protected Context mContext;  
  3.     protected PopupWindow mWindow;  
  4.     protected View mRootView;  
  5.     protected Drawable mBackground = null;  
  6.     protected WindowManager mWindowManager;  
  7.       
  8.     /** 
  9.      * Constructor. 
  10.      *  
  11.      * @param context Context 
  12.      */  
  13.     public PopupWindows(Context context) {  
  14.         mContext    = context;  
  15.         mWindow     = new PopupWindow(context);  
  16.   
  17.         mWindow.setTouchInterceptor(new OnTouchListener() {  
  18.             @Override  
  19.             public boolean onTouch(View v, MotionEvent event) {  
  20.                 if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {  
  21.                     mWindow.dismiss();  
  22.                       
  23.                     return true;  
  24.                 }  
  25.                   
  26.                 return false;  
  27.             }  
  28.         });  
  29.   
  30.         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
  31.     }  
  32.       
  33.     /** 
  34.      * On dismiss 
  35.      */  
  36.     protected void onDismiss() {          
  37.     }  
  38.       
  39.     /** 
  40.      * On show 
  41.      */  
  42.     protected void onShow() {         
  43.     }  
  44.   
  45.     /** 
  46.      * On pre show 
  47.      */  
  48.     protected void preShow() {  
  49.         if (mRootView == null)   
  50.             throw new IllegalStateException("setContentView was not called with a view to display.");  
  51.       
  52.         onShow();  
  53.   
  54.         if (mBackground == null)   
  55.             mWindow.setBackgroundDrawable(new BitmapDrawable());  
  56.         else   
  57.             mWindow.setBackgroundDrawable(mBackground);  
  58.   
  59.         mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);  
  60.         mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);  
  61.         mWindow.setTouchable(true);  
  62.         mWindow.setFocusable(true);  
  63.         mWindow.setOutsideTouchable(true);  
  64.   
  65.         mWindow.setContentView(mRootView);  
  66.     }  
  67.   
  68.     /** 
  69.      * Set background drawable. 
  70.      *  
  71.      * @param background Background drawable 
  72.      */  
  73.     public void setBackgroundDrawable(Drawable background) {  
  74.         mBackground = background;  
  75.     }  
  76.   
  77.     /** 
  78.      * Set content view. 
  79.      *  
  80.      * @param root Root view 
  81.      */  
  82.     public void setContentView(View root) {  
  83.         mRootView = root;  
  84.           
  85.         mWindow.setContentView(root);  
  86.     }  
  87.   
  88.     /** 
  89.      * Set content view. 
  90.      *  
  91.      * @param layoutResID Resource id 
  92.      */  
  93.     public void setContentView(int layoutResID) {  
  94.         LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  95.           
  96.         setContentView(inflator.inflate(layoutResID, null));  
  97.     }  
  98.   
  99.     /** 
  100.      * Set listener on window dismissed. 
  101.      *  
  102.      * @param listener 
  103.      */  
  104.     public void setOnDismissListener(PopupWindow.OnDismissListener listener) {  
  105.         mWindow.setOnDismissListener(listener);    
  106.     }  
  107.   
  108.     /** 
  109.      * Dismiss the popup window. 
  110.      */  
  111.     public void dismiss() {  
  112.         mWindow.dismiss();  
  113.     }  
  114. }  

 

 

Popu调用时在onCreate使用如下:

   

view plain
  1. PopuItem userItem   = new PopuItem(ID_USER, "用户", getResources().getDrawable(R.drawable.child_image));  
  2. PopuItem grounpItem     = new PopuItem(ID_GROUNP, "群组", getResources().getDrawable(R.drawable.user_group));    
  3.       //use setSticky(true) to disable PopuJar dialog being dismissed after an item is clicked  
  4.       userItem.setSticky(true);  
  5.   
  6. //create PopuJar. Use PopuJar.VERTICAL or PopuJar.HORIZONTAL param to define layout   
  7. final PopuJar mPopu = new PopuJar(this, PopuJar.VERTICAL);  
  8.   
  9. //add action items into PopuJar  
  10. mPopu.addPopuItem(userItem);  
  11. mPopu.addPopuItem(grounpItem);  



显示popu:

view plain
  1. mPopu.show(v); //v表示显示在那个view下面  

 

 

 

参考:

http://code.google.com/p/simple-quickactions/


转自 http://blog.csdn.net/xyz_lmn/article/details/6921097