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

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


前言


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


实现


package com.roc.actionsheet;

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

/**
 * ActionSheet
 * 
 * @author Mr.Zheng
 * @date 2014年9月7日 下午11:15:54
 */
public class ActionSheet extends Dialog implements OnClickListener
{
	/* 控件的id */
	private static final int CANCEL_BUTTON_ID = 100;
	private static final int BG_VIEW_ID = 10;
	private static final int TRANSLATE_DURATION = 300;
	private static final int ALPHA_DURATION = 300;

	private Context mContext;
	private Attributes mAttrs;
	private MenuItemClickListener mListener;
	private View mView;
	private LinearLayout mPanel;
	private View mBg;
	private List items;
	private String cancelTitle = "";
	private boolean mCancelableOnTouchOutside;
	private boolean mDismissed = true;
	private boolean isCancel = true;

	public ActionSheet(Context context)
	{
		super(context, android.R.style.Theme_Light_NoTitleBar);// 全屏
		this.mContext = context;
		initViews();
		getWindow().setGravity(Gravity.BOTTOM);
		Drawable drawable = new ColorDrawable();
		drawable.setAlpha(0);// 设置透明背景
		getWindow().setBackgroundDrawable(drawable);
	}

	public void initViews()
	{
		/* 隐藏软键盘 */
		InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm.isActive())
		{
			View focusView = ((Activity) mContext).getCurrentFocus();
			if (focusView != null)
				imm.hideSoftInputFromWindow(focusView.getWindowToken(), 0);
		}
		mAttrs = readAttribute();// 获取主题属性
		mView = createView();
		mBg.startAnimation(createAlphaInAnimation());
		mPanel.startAnimation(createTranslationInAnimation());
	}

	private Animation createTranslationInAnimation()
	{
		int type = TranslateAnimation.RELATIVE_TO_SELF;
		TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, 1, type, 0);
		an.setDuration(TRANSLATE_DURATION);
		return an;
	}

	private Animation createAlphaInAnimation()
	{
		AlphaAnimation an = new AlphaAnimation(0, 1);
		an.setDuration(ALPHA_DURATION);
		return an;
	}

	private Animation createTranslationOutAnimation()
	{
		int type = TranslateAnimation.RELATIVE_TO_SELF;
		TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, 0, type, 1);
		an.setDuration(TRANSLATE_DURATION);
		an.setFillAfter(true);
		return an;
	}

	private Animation createAlphaOutAnimation()
	{
		AlphaAnimation an = new AlphaAnimation(1, 0);
		an.setDuration(ALPHA_DURATION);
		an.setFillAfter(true);
		return an;
	}

	/**
	 * 创建基本的背景视图
	 */
	private View createView()
	{
		FrameLayout parent = new FrameLayout(mContext);
		FrameLayout.LayoutParams parentParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		parentParams.gravity = Gravity.BOTTOM;
		parent.setLayoutParams(parentParams);
		mBg = new View(mContext);
		mBg.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		mBg.setBackgroundColor(Color.argb(136, 0, 0, 0));
		mBg.setId(BG_VIEW_ID);
		mBg.setOnClickListener(this);

		mPanel = new LinearLayout(mContext);
		FrameLayout.LayoutParams mPanelParams = new FrameLayout.LayoutParams(
				FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
		mPanelParams.gravity = Gravity.BOTTOM;
		mPanel.setLayoutParams(mPanelParams);
		mPanel.setOrientation(LinearLayout.VERTICAL);
		parent.addView(mBg);
		parent.addView(mPanel);
		return parent;
	}

	/**
	 * 创建MenuItem
	 */
	private void createItems()
	{
		if (items != null && items.size() > 0)
			for (int i = 0; i < items.size(); i++)
			{
				Button bt = new Button(mContext);
				bt.setId(CANCEL_BUTTON_ID + i + 1);
				bt.setOnClickListener(this);
				bt.setBackgroundDrawable(getOtherButtonBg(items.toArray(new String[items.size()]), i));
				bt.setText(items.get(i));
				bt.setTextColor(mAttrs.otherButtonTextColor);
				bt.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttrs.actionSheetTextSize);
				if (i > 0)
				{
					LinearLayout.LayoutParams params = createButtonLayoutParams();
					params.topMargin = mAttrs.otherButtonSpacing;
					mPanel.addView(bt, params);
				} else
					mPanel.addView(bt);
			}
		Button bt = new Button(mContext);
		bt.getPaint().setFakeBoldText(true);
		bt.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttrs.actionSheetTextSize);
		bt.setId(CANCEL_BUTTON_ID);
		bt.setBackgroundDrawable(mAttrs.cancelButtonBackground);
		bt.setText(cancelTitle);
		bt.setTextColor(mAttrs.cancelButtonTextColor);
		bt.setOnClickListener(this);
		LinearLayout.LayoutParams params = createButtonLayoutParams();
		params.topMargin = mAttrs.cancelButtonMarginTop;
		mPanel.addView(bt, params);

		mPanel.setBackgroundDrawable(mAttrs.background);
		mPanel.setPadding(mAttrs.padding, mAttrs.padding, mAttrs.padding, mAttrs.padding);
	}

	public LinearLayout.LayoutParams createButtonLayoutParams()
	{
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.WRAP_CONTENT);
		return params;
	}

	/**
	 * item按钮的颜色
	 * 
	 * @param titles
	 * @param i
	 * @return
	 */
	private Drawable getOtherButtonBg(String[] titles, int i)
	{
		if (titles.length == 1)
			return mAttrs.otherButtonSingleBackground;
		else if (titles.length == 2)
			switch (i)
			{
			case 0:
				return mAttrs.otherButtonTopBackground;
			case 1:
				return mAttrs.otherButtonBottomBackground;
			}
		else if (titles.length > 2)
		{
			if (i == 0)
				return mAttrs.otherButtonTopBackground;
			else if (i == (titles.length - 1))
				return mAttrs.otherButtonBottomBackground;
			return mAttrs.getOtherButtonMiddleBackground();
		}
		return null;
	}

	public void showMenu()
	{
		if (!mDismissed)
			return;
		show();
		getWindow().setContentView(mView);
		mDismissed = false;
	}

	/**
	 * dissmiss Menu菜单
	 */
	public void dismissMenu()
	{
		if (mDismissed)
			return;
		dismiss();
		onDismiss();
		mDismissed = true;
	}

	/**
	 * dismiss时的处理
	 */
	private void onDismiss()
	{
		mPanel.startAnimation(createTranslationOutAnimation());
		mBg.startAnimation(createAlphaOutAnimation());
	}

	/**
	 * 取消按钮的标题文字
	 * 
	 * @param title
	 * @return
	 */
	public ActionSheet setCancelButtonTitle(String title)
	{
		this.cancelTitle = title;
		return this;
	}

	/**
	 * 取消按钮的标题文字
	 * 
	 * @param strId
	 * @return
	 */
	public ActionSheet setCancelButtonTitle(int strId)
	{
		return setCancelButtonTitle(mContext.getString(strId));
	}

	/**
	 * 点击外部边缘是否可取消
	 * 
	 * @param cancelable
	 * @return
	 */
	public ActionSheet setCancelableOnTouchMenuOutside(boolean cancelable)
	{
		mCancelableOnTouchOutside = cancelable;
		return this;
	}

	public ActionSheet addItems(String... titles)
	{
		if (titles == null || titles.length == 0)
			return this;
		items = Arrays.asList(titles);
		createItems();
		return this;
	}

	public ActionSheet setItemClickListener(MenuItemClickListener listener)
	{
		this.mListener = listener;
		return this;
	}

	private Attributes readAttribute()
	{
		Attributes attrs = new Attributes(mContext);
		TypedArray a = mContext.getTheme().obtainStyledAttributes(null, R.styleable.ActionSheet,
				R.attr.actionSheetStyle, 0);
		Drawable background = a.getDrawable(R.styleable.ActionSheet_actionSheetBackground);
		if (background != null)
			attrs.background = background;
		Drawable cancelButtonBackground = a.getDrawable(R.styleable.ActionSheet_cancelButtonBackground);
		if (cancelButtonBackground != null)
			attrs.cancelButtonBackground = cancelButtonBackground;
		Drawable otherButtonTopBackground = a.getDrawable(R.styleable.ActionSheet_otherButtonTopBackground);
		if (otherButtonTopBackground != null)
			attrs.otherButtonTopBackground = otherButtonTopBackground;
		Drawable otherButtonMiddleBackground = a
				.getDrawable(R.styleable.ActionSheet_otherButtonMiddleBackground);
		if (otherButtonMiddleBackground != null)
			attrs.otherButtonMiddleBackground = otherButtonMiddleBackground;
		Drawable otherButtonBottomBackground = a
				.getDrawable(R.styleable.ActionSheet_otherButtonBottomBackground);
		if (otherButtonBottomBackground != null)
			attrs.otherButtonBottomBackground = otherButtonBottomBackground;
		Drawable otherButtonSingleBackground = a
				.getDrawable(R.styleable.ActionSheet_otherButtonSingleBackground);
		if (otherButtonSingleBackground != null)
			attrs.otherButtonSingleBackground = otherButtonSingleBackground;
		attrs.cancelButtonTextColor = a.getColor(R.styleable.ActionSheet_cancelButtonTextColor,
				attrs.cancelButtonTextColor);
		attrs.otherButtonTextColor = a.getColor(R.styleable.ActionSheet_otherButtonTextColor,
				attrs.otherButtonTextColor);
		attrs.padding = (int) a.getDimension(R.styleable.ActionSheet_actionSheetPadding, attrs.padding);
		attrs.otherButtonSpacing = (int) a.getDimension(R.styleable.ActionSheet_otherButtonSpacing,
				attrs.otherButtonSpacing);
		attrs.cancelButtonMarginTop = (int) a.getDimension(R.styleable.ActionSheet_cancelButtonMarginTop,
				attrs.cancelButtonMarginTop);
		attrs.actionSheetTextSize = a.getDimensionPixelSize(R.styleable.ActionSheet_actionSheetTextSize,
				(int) attrs.actionSheetTextSize);

		a.recycle();
		return attrs;
	}

	@Override
	public void onClick(View v)
	{
		if (v.getId() == BG_VIEW_ID && !mCancelableOnTouchOutside)
			return;
		dismissMenu();
		if (v.getId() != CANCEL_BUTTON_ID && v.getId() != BG_VIEW_ID)
		{
			if (mListener != null)
				mListener.onItemClick(v.getId() - CANCEL_BUTTON_ID - 1);
			isCancel = false;
		}
	}

	/**
	 * 自定义属性的控件主题
	 * 
	 * @author Mr.Zheng
	 * @date 2014年9月7日 下午10:47:06
	 */
	private class Attributes
	{
		private Context mContext;

		private Drawable background;
		private Drawable cancelButtonBackground;
		private Drawable otherButtonTopBackground;
		private Drawable otherButtonMiddleBackground;
		private Drawable otherButtonBottomBackground;
		private Drawable otherButtonSingleBackground;
		private int cancelButtonTextColor;
		private int otherButtonTextColor;
		private int padding;
		private int otherButtonSpacing;
		private int cancelButtonMarginTop;
		private float actionSheetTextSize;

		public Attributes(Context context)
		{
			mContext = context;
			this.background = new ColorDrawable(Color.TRANSPARENT);
			this.cancelButtonBackground = new ColorDrawable(Color.BLACK);
			ColorDrawable gray = new ColorDrawable(Color.GRAY);
			this.otherButtonTopBackground = gray;
			this.otherButtonMiddleBackground = gray;
			this.otherButtonBottomBackground = gray;
			this.otherButtonSingleBackground = gray;
			this.cancelButtonTextColor = Color.WHITE;
			this.otherButtonTextColor = Color.BLACK;
			this.padding = dp2px(20);
			this.otherButtonSpacing = dp2px(2);
			this.cancelButtonMarginTop = dp2px(10);
			this.actionSheetTextSize = dp2px(16);
		}

		private int dp2px(int dp)
		{
			return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources()
					.getDisplayMetrics());
		}

		public Drawable getOtherButtonMiddleBackground()
		{
			if (otherButtonMiddleBackground instanceof StateListDrawable)
			{
				TypedArray a = mContext.getTheme().obtainStyledAttributes(null, R.styleable.ActionSheet,
						R.attr.actionSheetStyle, 0);
				otherButtonMiddleBackground = a
						.getDrawable(R.styleable.ActionSheet_otherButtonMiddleBackground);
				a.recycle();
			}
			return otherButtonMiddleBackground;
		}

	}

	public static interface MenuItemClickListener
	{
		void onItemClick(int itemPosition);
	}

}

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


使用

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

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



    

    


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

package com.roc.actionsheet;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.Toast;

import com.roc.actionsheet.ActionSheet.MenuItemClickListener;

/**
 * @author Mr.Zheng
 * @date 2014年9月8日  上午12:08:55
 */
public class MainActivity extends FragmentActivity implements MenuItemClickListener
{

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void onClick(View v)
	{
		switch (v.getId())
		{
		case R.id.ios6:
			setTheme(R.style.ActionSheetStyleIOS6);
			break;
		case R.id.ios7:
			setTheme(R.style.ActionSheetStyleIOS7);
			break;
		}
		showActionSheet();
	}

	public void showActionSheet()
	{
		ActionSheet menuView = new ActionSheet(this);
		menuView.setCancelButtonTitle("cancel");// before add items
		menuView.addItems("Item1", "Item2", "Item3", "Item4");
		menuView.setItemClickListener(this);
		menuView.setCancelableOnTouchMenuOutside(true);
		menuView.showMenu();
	}

	@Override
	public void onItemClick(int itemPosition)
	{
		Toast.makeText(this, (itemPosition + 1) + " click", 0).show();
	}

}

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

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


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



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







你可能感兴趣的:(Android)