Android 使用自定义Dialog打造ActionSheet菜单

转载请注明出处:http://blog.csdn.net/bbld_/article/details/39124097


前言


这几天用到了github上的一个仿IOS的ActionSheet(ActionSheetForAndroid)控件,它是使用Fragment实现的,由于我的主界面也是由几个Fragment来做,所以这样会造成FragmentManager出现一些问题。所以就把它的实现方式改为由自定义Dialog来实现,保留它的主题属性方便修改样式,同时去除Fragmrnt部分,增加可用性。


实现


[java]  view plain copy
  1. package com.roc.actionsheet;  
  2.   
  3. import java.util.Arrays;  
  4. import java.util.List;  
  5.   
  6. import android.app.Activity;  
  7. import android.app.Dialog;  
  8. import android.content.Context;  
  9. import android.content.res.TypedArray;  
  10. import android.graphics.Color;  
  11. import android.graphics.drawable.ColorDrawable;  
  12. import android.graphics.drawable.Drawable;  
  13. import android.graphics.drawable.StateListDrawable;  
  14. import android.util.TypedValue;  
  15. import android.view.Gravity;  
  16. import android.view.View;  
  17. import android.view.View.OnClickListener;  
  18. import android.view.ViewGroup.LayoutParams;  
  19. import android.view.animation.AlphaAnimation;  
  20. import android.view.animation.Animation;  
  21. import android.view.animation.TranslateAnimation;  
  22. import android.view.inputmethod.InputMethodManager;  
  23. import android.widget.Button;  
  24. import android.widget.FrameLayout;  
  25. import android.widget.LinearLayout;  
  26.   
  27. /** 
  28.  * ActionSheet 
  29.  *  
  30.  * @author Mr.Zheng 
  31.  * @date 2014年9月7日 下午11:15:54 
  32.  */  
  33. public class ActionSheet extends Dialog implements OnClickListener  
  34. {  
  35.     /* 控件的id */  
  36.     private static final int CANCEL_BUTTON_ID = 100;  
  37.     private static final int BG_VIEW_ID = 10;  
  38.     private static final int TRANSLATE_DURATION = 300;  
  39.     private static final int ALPHA_DURATION = 300;  
  40.   
  41.     private Context mContext;  
  42.     private Attributes mAttrs;  
  43.     private MenuItemClickListener mListener;  
  44.     private View mView;  
  45.     private LinearLayout mPanel;  
  46.     private View mBg;  
  47.     private List<String> items;  
  48.     private String cancelTitle = "";  
  49.     private boolean mCancelableOnTouchOutside;  
  50.     private boolean mDismissed = true;  
  51.     private boolean isCancel = true;  
  52.   
  53.     public ActionSheet(Context context)  
  54.     {  
  55.         super(context, android.R.style.Theme_Light_NoTitleBar);// 全屏  
  56.         this.mContext = context;  
  57.         initViews();  
  58.         getWindow().setGravity(Gravity.BOTTOM);  
  59.         Drawable drawable = new ColorDrawable();  
  60.         drawable.setAlpha(0);// 设置透明背景  
  61.         getWindow().setBackgroundDrawable(drawable);  
  62.     }  
  63.   
  64.     public void initViews()  
  65.     {  
  66.         /* 隐藏软键盘 */  
  67.         InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);  
  68.         if (imm.isActive())  
  69.         {  
  70.             View focusView = ((Activity) mContext).getCurrentFocus();  
  71.             if (focusView != null)  
  72.                 imm.hideSoftInputFromWindow(focusView.getWindowToken(), 0);  
  73.         }  
  74.         mAttrs = readAttribute();// 获取主题属性  
  75.         mView = createView();  
  76.         mBg.startAnimation(createAlphaInAnimation());  
  77.         mPanel.startAnimation(createTranslationInAnimation());  
  78.     }  
  79.   
  80.     private Animation createTranslationInAnimation()  
  81.     {  
  82.         int type = TranslateAnimation.RELATIVE_TO_SELF;  
  83.         TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, 1, type, 0);  
  84.         an.setDuration(TRANSLATE_DURATION);  
  85.         return an;  
  86.     }  
  87.   
  88.     private Animation createAlphaInAnimation()  
  89.     {  
  90.         AlphaAnimation an = new AlphaAnimation(01);  
  91.         an.setDuration(ALPHA_DURATION);  
  92.         return an;  
  93.     }  
  94.   
  95.     private Animation createTranslationOutAnimation()  
  96.     {  
  97.         int type = TranslateAnimation.RELATIVE_TO_SELF;  
  98.         TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, 0, type, 1);  
  99.         an.setDuration(TRANSLATE_DURATION);  
  100.         an.setFillAfter(true);  
  101.         return an;  
  102.     }  
  103.   
  104.     private Animation createAlphaOutAnimation()  
  105.     {  
  106.         AlphaAnimation an = new AlphaAnimation(10);  
  107.         an.setDuration(ALPHA_DURATION);  
  108.         an.setFillAfter(true);  
  109.         return an;  
  110.     }  
  111.   
  112.     /** 
  113.      * 创建基本的背景视图 
  114.      */  
  115.     private View createView()  
  116.     {  
  117.         FrameLayout parent = new FrameLayout(mContext);  
  118.         FrameLayout.LayoutParams parentParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,  
  119.                 LayoutParams.MATCH_PARENT);  
  120.         parentParams.gravity = Gravity.BOTTOM;  
  121.         parent.setLayoutParams(parentParams);  
  122.         mBg = new View(mContext);  
  123.         mBg.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));  
  124.         mBg.setBackgroundColor(Color.argb(136000));  
  125.         mBg.setId(BG_VIEW_ID);  
  126.         mBg.setOnClickListener(this);  
  127.   
  128.         mPanel = new LinearLayout(mContext);  
  129.         FrameLayout.LayoutParams mPanelParams = new FrameLayout.LayoutParams(  
  130.                 FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);  
  131.         mPanelParams.gravity = Gravity.BOTTOM;  
  132.         mPanel.setLayoutParams(mPanelParams);  
  133.         mPanel.setOrientation(LinearLayout.VERTICAL);  
  134.         parent.addView(mBg);  
  135.         parent.addView(mPanel);  
  136.         return parent;  
  137.     }  
  138.   
  139.     /** 
  140.      * 创建MenuItem 
  141.      */  
  142.     private void createItems()  
  143.     {  
  144.         if (items != null && items.size() > 0)  
  145.             for (int i = 0; i < items.size(); i++)  
  146.             {  
  147.                 Button bt = new Button(mContext);  
  148.                 bt.setId(CANCEL_BUTTON_ID + i + 1);  
  149.                 bt.setOnClickListener(this);  
  150.                 bt.setBackgroundDrawable(getOtherButtonBg(items.toArray(new String[items.size()]), i));  
  151.                 bt.setText(items.get(i));  
  152.                 bt.setTextColor(mAttrs.otherButtonTextColor);  
  153.                 bt.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttrs.actionSheetTextSize);  
  154.                 if (i > 0)  
  155.                 {  
  156.                     LinearLayout.LayoutParams params = createButtonLayoutParams();  
  157.                     params.topMargin = mAttrs.otherButtonSpacing;  
  158.                     mPanel.addView(bt, params);  
  159.                 } else  
  160.                     mPanel.addView(bt);  
  161.             }  
  162.         Button bt = new Button(mContext);  
  163.         bt.getPaint().setFakeBoldText(true);  
  164.         bt.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttrs.actionSheetTextSize);  
  165.         bt.setId(CANCEL_BUTTON_ID);  
  166.         bt.setBackgroundDrawable(mAttrs.cancelButtonBackground);  
  167.         bt.setText(cancelTitle);  
  168.         bt.setTextColor(mAttrs.cancelButtonTextColor);  
  169.         bt.setOnClickListener(this);  
  170.         LinearLayout.LayoutParams params = createButtonLayoutParams();  
  171.         params.topMargin = mAttrs.cancelButtonMarginTop;  
  172.         mPanel.addView(bt, params);  
  173.   
  174.         mPanel.setBackgroundDrawable(mAttrs.background);  
  175.         mPanel.setPadding(mAttrs.padding, mAttrs.padding, mAttrs.padding, mAttrs.padding);  
  176.     }  
  177.   
  178.     public LinearLayout.LayoutParams createButtonLayoutParams()  
  179.     {  
  180.         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,  
  181.                 LayoutParams.WRAP_CONTENT);  
  182.         return params;  
  183.     }  
  184.   
  185.     /** 
  186.      * item按钮的颜色 
  187.      *  
  188.      * @param titles 
  189.      * @param i 
  190.      * @return 
  191.      */  
  192.     private Drawable getOtherButtonBg(String[] titles, int i)  
  193.     {  
  194.         if (titles.length == 1)  
  195.             return mAttrs.otherButtonSingleBackground;  
  196.         else if (titles.length == 2)  
  197.             switch (i)  
  198.             {  
  199.             case 0:  
  200.                 return mAttrs.otherButtonTopBackground;  
  201.             case 1:  
  202.                 return mAttrs.otherButtonBottomBackground;  
  203.             }  
  204.         else if (titles.length > 2)  
  205.         {  
  206.             if (i == 0)  
  207.                 return mAttrs.otherButtonTopBackground;  
  208.             else if (i == (titles.length - 1))  
  209.                 return mAttrs.otherButtonBottomBackground;  
  210.             return mAttrs.getOtherButtonMiddleBackground();  
  211.         }  
  212.         return null;  
  213.     }  
  214.   
  215.     public void showMenu()  
  216.     {  
  217.         if (!mDismissed)  
  218.             return;  
  219.         show();  
  220.         getWindow().setContentView(mView);  
  221.         mDismissed = false;  
  222.     }  
  223.   
  224.     /** 
  225.      * dissmiss Menu菜单 
  226.      */  
  227.     public void dismissMenu()  
  228.     {  
  229.         if (mDismissed)  
  230.             return;  
  231.         dismiss();  
  232.         onDismiss();  
  233.         mDismissed = true;  
  234.     }  
  235.   
  236.     /** 
  237.      * dismiss时的处理 
  238.      */  
  239.     private void onDismiss()  
  240.     {  
  241.         mPanel.startAnimation(createTranslationOutAnimation());  
  242.         mBg.startAnimation(createAlphaOutAnimation());  
  243.     }  
  244.   
  245.     /** 
  246.      * 取消按钮的标题文字 
  247.      *  
  248.      * @param title 
  249.      * @return 
  250.      */  
  251.     public ActionSheet setCancelButtonTitle(String title)  
  252.     {  
  253.         this.cancelTitle = title;  
  254.         return this;  
  255.     }  
  256.   
  257.     /** 
  258.      * 取消按钮的标题文字 
  259.      *  
  260.      * @param strId 
  261.      * @return 
  262.      */  
  263.     public ActionSheet setCancelButtonTitle(int strId)  
  264.     {  
  265.         return setCancelButtonTitle(mContext.getString(strId));  
  266.     }  
  267.   
  268.     /** 
  269.      * 点击外部边缘是否可取消 
  270.      *  
  271.      * @param cancelable 
  272.      * @return 
  273.      */  
  274.     public ActionSheet setCancelableOnTouchMenuOutside(boolean cancelable)  
  275.     {  
  276.         mCancelableOnTouchOutside = cancelable;  
  277.         return this;  
  278.     }  
  279.   
  280.     public ActionSheet addItems(String... titles)  
  281.     {  
  282.         if (titles == null || titles.length == 0)  
  283.             return this;  
  284.         items = Arrays.asList(titles);  
  285.         createItems();  
  286.         return this;  
  287.     }  
  288.   
  289.     public ActionSheet setItemClickListener(MenuItemClickListener listener)  
  290.     {  
  291.         this.mListener = listener;  
  292.         return this;  
  293.     }  
  294.   
  295.     private Attributes readAttribute()  
  296.     {  
  297.         Attributes attrs = new Attributes(mContext);  
  298.         TypedArray a = mContext.getTheme().obtainStyledAttributes(null, R.styleable.ActionSheet,  
  299.                 R.attr.actionSheetStyle, 0);  
  300.         Drawable background = a.getDrawable(R.styleable.ActionSheet_actionSheetBackground);  
  301.         if (background != null)  
  302.             attrs.background = background;  
  303.         Drawable cancelButtonBackground = a.getDrawable(R.styleable.ActionSheet_cancelButtonBackground);  
  304.         if (cancelButtonBackground != null)  
  305.             attrs.cancelButtonBackground = cancelButtonBackground;  
  306.         Drawable otherButtonTopBackground = a.getDrawable(R.styleable.ActionSheet_otherButtonTopBackground);  
  307.         if (otherButtonTopBackground != null)  
  308.             attrs.otherButtonTopBackground = otherButtonTopBackground;  
  309.         Drawable otherButtonMiddleBackground = a  
  310.                 .getDrawable(R.styleable.ActionSheet_otherButtonMiddleBackground);  
  311.         if (otherButtonMiddleBackground != null)  
  312.             attrs.otherButtonMiddleBackground = otherButtonMiddleBackground;  
  313.         Drawable otherButtonBottomBackground = a  
  314.                 .getDrawable(R.styleable.ActionSheet_otherButtonBottomBackground);  
  315.         if (otherButtonBottomBackground != null)  
  316.             attrs.otherButtonBottomBackground = otherButtonBottomBackground;  
  317.         Drawable otherButtonSingleBackground = a  
  318.                 .getDrawable(R.styleable.ActionSheet_otherButtonSingleBackground);  
  319.         if (otherButtonSingleBackground != null)  
  320.             attrs.otherButtonSingleBackground = otherButtonSingleBackground;  
  321.         attrs.cancelButtonTextColor = a.getColor(R.styleable.ActionSheet_cancelButtonTextColor,  
  322.                 attrs.cancelButtonTextColor);  
  323.         attrs.otherButtonTextColor = a.getColor(R.styleable.ActionSheet_otherButtonTextColor,  
  324.                 attrs.otherButtonTextColor);  
  325.         attrs.padding = (int) a.getDimension(R.styleable.ActionSheet_actionSheetPadding, attrs.padding);  
  326.         attrs.otherButtonSpacing = (int) a.getDimension(R.styleable.ActionSheet_otherButtonSpacing,  
  327.                 attrs.otherButtonSpacing);  
  328.         attrs.cancelButtonMarginTop = (int) a.getDimension(R.styleable.ActionSheet_cancelButtonMarginTop,  
  329.                 attrs.cancelButtonMarginTop);  
  330.         attrs.actionSheetTextSize = a.getDimensionPixelSize(R.styleable.ActionSheet_actionSheetTextSize,  
  331.                 (int) attrs.actionSheetTextSize);  
  332.   
  333.         a.recycle();  
  334.         return attrs;  
  335.     }  
  336.   
  337.     @Override  
  338.     public void onClick(View v)  
  339.     {  
  340.         if (v.getId() == BG_VIEW_ID && !mCancelableOnTouchOutside)  
  341.             return;  
  342.         dismissMenu();  
  343.         if (v.getId() != CANCEL_BUTTON_ID && v.getId() != BG_VIEW_ID)  
  344.         {  
  345.             if (mListener != null)  
  346.                 mListener.onItemClick(v.getId() - CANCEL_BUTTON_ID - 1);  
  347.             isCancel = false;  
  348.         }  
  349.     }  
  350.   
  351.     /** 
  352.      * 自定义属性的控件主题 
  353.      *  
  354.      * @author Mr.Zheng 
  355.      * @date 2014年9月7日 下午10:47:06 
  356.      */  
  357.     private class Attributes  
  358.     {  
  359.         private Context mContext;  
  360.   
  361.         private Drawable background;  
  362.         private Drawable cancelButtonBackground;  
  363.         private Drawable otherButtonTopBackground;  
  364.         private Drawable otherButtonMiddleBackground;  
  365.         private Drawable otherButtonBottomBackground;  
  366.         private Drawable otherButtonSingleBackground;  
  367.         private int cancelButtonTextColor;  
  368.         private int otherButtonTextColor;  
  369.         private int padding;  
  370.         private int otherButtonSpacing;  
  371.         private int cancelButtonMarginTop;  
  372.         private float actionSheetTextSize;  
  373.   
  374.         public Attributes(Context context)  
  375.         {  
  376.             mContext = context;  
  377.             this.background = new ColorDrawable(Color.TRANSPARENT);  
  378.             this.cancelButtonBackground = new ColorDrawable(Color.BLACK);  
  379.             ColorDrawable gray = new ColorDrawable(Color.GRAY);  
  380.             this.otherButtonTopBackground = gray;  
  381.             this.otherButtonMiddleBackground = gray;  
  382.             this.otherButtonBottomBackground = gray;  
  383.             this.otherButtonSingleBackground = gray;  
  384.             this.cancelButtonTextColor = Color.WHITE;  
  385.             this.otherButtonTextColor = Color.BLACK;  
  386.             this.padding = dp2px(20);  
  387.             this.otherButtonSpacing = dp2px(2);  
  388.             this.cancelButtonMarginTop = dp2px(10);  
  389.             this.actionSheetTextSize = dp2px(16);  
  390.         }  
  391.   
  392.         private int dp2px(int dp)  
  393.         {  
  394.             return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources()  
  395.                     .getDisplayMetrics());  
  396.         }  
  397.   
  398.         public Drawable getOtherButtonMiddleBackground()  
  399.         {  
  400.             if (otherButtonMiddleBackground instanceof StateListDrawable)  
  401.             {  
  402.                 TypedArray a = mContext.getTheme().obtainStyledAttributes(null, R.styleable.ActionSheet,  
  403.                         R.attr.actionSheetStyle, 0);  
  404.                 otherButtonMiddleBackground = a  
  405.                         .getDrawable(R.styleable.ActionSheet_otherButtonMiddleBackground);  
  406.                 a.recycle();  
  407.             }  
  408.             return otherButtonMiddleBackground;  
  409.         }  
  410.   
  411.     }  
  412.   
  413.     public static interface MenuItemClickListener  
  414.     {  
  415.         void onItemClick(int itemPosition);  
  416.     }  
  417.   
  418. }  

代码中要注意的地方就是dialog的自定义view要在底部出现,背景要透明,dialog要全屏,这些主要在 ActionSheet 构造方法里设置,即55到61行,然后动态添加控件时注意一下Params就好。其它地方也没什么改动了。


使用

主题我也是直接使用它的,资源配置文件就不贴上来了,其中的属性代表的对应控件去参看ActionSheetForAndroid吧,最后贴上源码地址,改大小、颜色、背景什么的到主题里设置一下换下图片就行了。

我们可以在style直接设置ActionSheet的主题:

[html]  view plain copy
  1. <resources>  
  2.   
  3.     <style name="AppBaseTheme" parent="android:Theme.Light.NoTitleBar"></style>  
  4.   
  5.     <style name="AppTheme" parent="AppBaseTheme">  
  6.   
  7.         <!-- ActionSheet -->  
  8.         <item name="actionSheetBackground">@android:color/transparent</item>  
  9.         <item name="cancelButtonBackground">@drawable/actionsheet_slt_as_ios7_cancel_bt</item>  
  10.         <item name="otherButtonTopBackground">@drawable/actionsheet_slt_as_ios7_other_bt_top</item>  
  11.         <item name="otherButtonMiddleBackground">@drawable/actionsheet_slt_as_ios7_other_bt_middle</item>  
  12.         <item name="otherButtonBottomBackground">@drawable/actionsheet_slt_as_ios7_other_bt_bottom</item>  
  13.         <item name="otherButtonSingleBackground">@drawable/actionsheet_slt_as_ios7_other_bt_single</item>  
  14.         <item name="cancelButtonTextColor">#1E82FF</item>  
  15.         <item name="otherButtonTextColor">#1E82FF</item>  
  16.         <item name="actionSheetPadding">10dp</item>  
  17.         <item name="otherButtonSpacing">0dp</item>  
  18.         <item name="cancelButtonMarginTop">10dp</item>  
  19.         <item name="actionSheetTextSize">16sp</item>  
  20.     </style>  
  21.   
  22. </resources>  

也可以在代码里才去设置主题:

[java]  view plain copy
  1. package com.roc.actionsheet;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v4.app.FragmentActivity;  
  5. import android.view.View;  
  6. import android.widget.Toast;  
  7.   
  8. import com.roc.actionsheet.ActionSheet.MenuItemClickListener;  
  9.   
  10. /** 
  11.  * @author Mr.Zheng 
  12.  * @date 2014年9月8日  上午12:08:55 
  13.  */  
  14. public class MainActivity extends FragmentActivity implements MenuItemClickListener  
  15. {  
  16.   
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState)  
  19.     {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_main);  
  22.     }  
  23.   
  24.     public void onClick(View v)  
  25.     {  
  26.         switch (v.getId())  
  27.         {  
  28.         case R.id.ios6:  
  29.             setTheme(R.style.ActionSheetStyleIOS6);  
  30.             break;  
  31.         case R.id.ios7:  
  32.             setTheme(R.style.ActionSheetStyleIOS7);  
  33.             break;  
  34.         }  
  35.         showActionSheet();  
  36.     }  
  37.   
  38.     public void showActionSheet()  
  39.     {  
  40.         ActionSheet menuView = new ActionSheet(this);  
  41.         menuView.setCancelButtonTitle("cancel");// before add items  
  42.         menuView.addItems("Item1""Item2""Item3""Item4");  
  43.         menuView.setItemClickListener(this);  
  44.         menuView.setCancelableOnTouchMenuOutside(true);  
  45.         menuView.showMenu();  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onItemClick(int itemPosition)  
  50.     {  
  51.         Toast.makeText(this, (itemPosition + 1) + " click"0).show();  
  52.     }  
  53.   
  54. }  

是不是挺简单的。下面来看下效果

Android 使用自定义Dialog打造ActionSheet菜单_第1张图片


效果是和用Fragment实现一样的。



源码下载地址:http://download.csdn.net/detail/bbld_/7878275

你可能感兴趣的:(Android 使用自定义Dialog打造ActionSheet菜单)