天天看点

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

转载请注明出处: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();  

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

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

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

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

继续阅读