转载请注明出处:http://blog.csdn.net/bbld_/article/details/39124097
前言
这几天用到了github上的一个仿ios的actionsheet(actionsheetforandroid)控件,它是使用fragment实现的,由于我的主界面也是由几个fragment来做,所以这样会造成fragmentmanager出现一些问题。所以就把它的实现方式改为由自定义dialog来实现,保留它的主题属性方便修改样式,同时去除fragmrnt部分,增加可用性。
实现
[java] view
plaincopy
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<string> 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);
private animation createtranslationoutanimation()
translateanimation an = new translateanimation(type, 0, type, 0, type, 0, type, 1);
an.setfillafter(true);
private animation createalphaoutanimation()
alphaanimation an = new alphaanimation(1, 0);
/**
* 创建基本的背景视图
*/
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)
else if (i == (titles.length - 1))
return mattrs.getotherbuttonmiddlebackground();
return null;
public void showmenu()
if (!mdismissed)
return;
show();
getwindow().setcontentview(mview);
mdismissed = false;
* dissmiss menu菜单
public void dismissmenu()
if (mdismissed)
dismiss();
ondismiss();
mdismissed = true;
* dismiss时的处理
private void ondismiss()
mpanel.startanimation(createtranslationoutanimation());
mbg.startanimation(createalphaoutanimation());
* 取消按钮的标题文字
* @param title
public actionsheet setcancelbuttontitle(string title)
this.canceltitle = title;
return this;
* @param strid
public actionsheet setcancelbuttontitle(int strid)
return setcancelbuttontitle(mcontext.getstring(strid));
* 点击外部边缘是否可取消
* @param cancelable
public actionsheet setcancelableontouchmenuoutside(boolean cancelable)
mcancelableontouchoutside = cancelable;
public actionsheet additems(string... titles)
if (titles == null || titles.length == 0)
return this;
items = arrays.aslist(titles);
createitems();
public actionsheet setitemclicklistener(menuitemclicklistener listener)
this.mlistener = listener;
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)
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的主题:
[html] view
<resources>
<style name="appbasetheme" parent="android:theme.light.notitlebar"></style>
<style name="apptheme" parent="appbasetheme">
<!-- actionsheet -->
<item name="actionsheetbackground">@android:color/transparent</item>
<item name="cancelbuttonbackground">@drawable/actionsheet_slt_as_ios7_cancel_bt</item>
<item name="otherbuttontopbackground">@drawable/actionsheet_slt_as_ios7_other_bt_top</item>
<item name="otherbuttonmiddlebackground">@drawable/actionsheet_slt_as_ios7_other_bt_middle</item>
<item name="otherbuttonbottombackground">@drawable/actionsheet_slt_as_ios7_other_bt_bottom</item>
<item name="otherbuttonsinglebackground">@drawable/actionsheet_slt_as_ios7_other_bt_single</item>
<item name="cancelbuttontextcolor">#1e82ff</item>
<item name="otherbuttontextcolor">#1e82ff</item>
<item name="actionsheetpadding">10dp</item>
<item name="otherbuttonspacing">0dp</item>
<item name="cancelbuttonmargintop">10dp</item>
<item name="actionsheettextsize">16sp</item>
</style>
</resources>
也可以在代码里才去设置主题:
import android.os.bundle;
import android.support.v4.app.fragmentactivity;
import android.widget.toast;
import com.roc.actionsheet.actionsheet.menuitemclicklistener;
* @date 2014年9月8日 上午12:08:55
public class mainactivity extends fragmentactivity implements menuitemclicklistener
protected void oncreate(bundle savedinstancestate)
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
switch (v.getid())
case r.id.ios6:
settheme(r.style.actionsheetstyleios6);
break;
case r.id.ios7:
settheme(r.style.actionsheetstyleios7);
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();
public void onitemclick(int itemposition)
toast.maketext(this, (itemposition + 1) + " click", 0).show();
是不是挺简单的。下面来看下效果
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIzUTOzUDMxIDM4ATOwQTMwIzLcRXZu5ibkN3Yuc2bsJmLn1Wavw1LcpDc0RHaiojIsJye.jpg)
效果是和用fragment实现一样的。
源码下载地址:http://download.csdn.net/detail/bbld_/7878275