簡(jiǎn)潔仿IOS的圓角Dialog

先上個(gè)效果圖 ,也可以根據(jù)自己需求词爬,添加控件秃嗜,也可以根據(jù)這種思路,自己去修改布局文件顿膨。

最后會(huì)給出源碼githup地址锅锨。


然后開始吧。
首先在styles文件里定義樣式恋沃。

<style name="AlertDialogStyle" parent="@android:style/Theme.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsTranslucent">true</item>
</style>

接著再drawable文件夾下自定義一個(gè)圓角的shape.

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- radius 為圓角半徑  -->

    <corners android:radius="20dp" ></corners>

    <solid android:color="#ffffff" />

</shape>

然后自定義一個(gè)dialog的xml布局, 并且設(shè)置背景引用圓角shape必搞。
android:background="@drawable/bg_course_dialog"
布局文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/bg_course_dialog"
    >


    <ImageView
        android:id="@+id/icon"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_marginTop="28dp"
        android:layout_toLeftOf="@+id/title"
        android:src="@mipmap/ic_launcher_round"
        android:visibility="gone"
        />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="25dp"
        android:textColor="#000000"
        android:textSize="20sp"
        android:textStyle="bold"
        tools:text="titletitletitle"
        />

    <LinearLayout
        android:id="@+id/ll_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="25dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="5dp"
        android:gravity="center"
        android:orientation="vertical"
        >

        <TextView
            android:id="@+id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="16sp"
            tools:text="message"/>
    </LinearLayout>


    <View
        android:id="@+id/line_horizontal"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_below="@+id/ll_content"
        android:visibility="gone"
        android:background="#dad6d6"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/line_horizontal"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/dialog_cancel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp"
            android:layout_weight="1"
            android:clickable="true"
            android:gravity="center"
            android:text="取消"
            android:textColor="#007aff"
            android:textSize="18sp"
            android:visibility="gone"/>

        <View
            android:id="@+id/line_vertical"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"
            android:background="#dad6d6"
            android:visibility="gone"/>

        <TextView
            android:id="@+id/dialog_commit"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="確認(rèn)"
            android:textColor="#007aff"
            android:textSize="18sp"
            android:visibility="gone"/>
    </LinearLayout>

</RelativeLayout>

然后是封裝的具體代碼。
這里使用alertdialog中的建造者模式Builder來(lái)建造囊咏,這樣可以方便我們建造不同需求的dialog恕洲。(如對(duì)建造者模式不了解的可以自己搜一下相關(guān)資料)

代碼很簡(jiǎn)單 首先是構(gòu)造一個(gè)Params來(lái)管理我們具體要build的屬性。

public static class Builder implements BuilderInterface {
    private Context mContext;
    private final ControllerParams mParams;
    private Controller mController;

    public Builder(Context context) {
        mContext = context;
        mParams = new ControllerParams();
        mController = new Controller(mContext);
    }

    public Builder setContentView(int layoutId) {
        mParams.setLayoutId(layoutId);
        return this;
    }

    public Builder setContentView(View view) {
        mParams.setContentView(view);
        return this;
    }

    public Builder setTitle(String title) {
        mParams.setTitle(title);
        return this;
    }

    public Builder reSetTitle(String title) {
        mParams.setTitle(title);
        mController.setTitle(title);
        return this;
    }

    public Builder reSetMessage(String message) {
        mParams.setMessage(message);
        mController.setMessage(message);
        return this;
    }

    public Builder reSetIcon(int iconId) {
        mParams.setIconId(iconId);
        mController.setIcon(iconId);
        return this;
    }

    public Builder setMessage(String message) {
        mParams.setMessage(message);
        return this;
    }

    public Builder setIcon(int iconId) {
        mParams.setIconId(iconId);
        return this;
    }

    public Builder setCancelable(boolean cancelable) {
        mParams.setCancelable(cancelable);
        return this;
    }


    public Builder setNegativeButton(String text, OnNegativeListener listener) {
        mParams.setNegativeListener(listener);
        mParams.setNegativeText(text);

        return this;
    }

    public Builder setPositiveButton(String text,  OnPositiveListener listener)  {
        mParams.setPositiveListener(listener);
        mParams.setPositiveText(text);
        return this;
    }

    /**
     * 建造dialog
     * @return dialog
     */
    public Dialog create() {
        Dialog dialog = new Dialog(mContext, R.style.AlertDialogStyle);
        //屬性交給controller去應(yīng)用到dialog上
        mParams.apply(mController, dialog);
        return dialog;
    }

    /**
     * 建造一個(gè)默認(rèn)的dialog
     * @param onPositiveListener 確認(rèn)按鍵監(jiān)聽
     * @param onNegativeListener 取消按鍵監(jiān)聽
     * @return dialog
     */
    public Dialog createDefault(OnPositiveListener onPositiveListener, OnNegativeListener onNegativeListener) {
        Dialog dialog = new Dialog(mContext, R.style.AlertDialogStyle);
        build(onPositiveListener, onNegativeListener);
        mParams.apply(mController, dialog);
        return dialog;
    }

    private void build(OnPositiveListener onPositiveListener, OnNegativeListener onNegativeListener) {
        setTitle("溫馨提示")
                .setMessage("確認(rèn)提交嗎")
                .setCancelable(false)
                .setPositiveButton("確認(rèn)", onPositiveListener)
                .setNegativeButton("取消", onNegativeListener);
    }
}

管理屬性的類核心方法就是apply(),在這里判斷是否緩存了屬性梅割,有的話就交給controller去設(shè)置給dialog.

/**
 * 管理dialog所有屬性的類
 */
private static class ControllerParams {
    private String mTitle;
    private String mMessage;
    private int mIconId = -1;
    private int mLayoutId = -1;
    private boolean mCancelable;
    private String mPositiveText;
    private String mNegativeText;
    private OnPositiveListener mPositiveListener;
    private OnNegativeListener mNegativeListener;
    private View mContentView;


    private void apply(Controller controller, Dialog dialog) {

        if (mContentView != null) {
            controller.setContentView(mContentView, dialog);
        }else {
            controller.setContentView(mLayoutId, dialog);
        }
        dialog.setCancelable(mCancelable);
        if (mCancelable) {
            dialog.setCanceledOnTouchOutside(true);
        }

        if (mTitle != null) {
            controller.setTitle(mTitle);
        }
        if (mMessage != null) {
            controller.setMessage(mMessage);
        }
        if (mPositiveText != null && mPositiveListener != null) {
            controller.setPositiveButton(mPositiveText, mPositiveListener);
        }
        if (mNegativeText != null && mNegativeListener != null) {
            controller.setNegativeButton(mNegativeText, mNegativeListener);
        }
        if (mIconId != -1) {
            controller.setIcon(mIconId);
        }


    }


    public int getLayoutId() {
        return mLayoutId;
    }

    private void setLayoutId(int layoutId) {
        mLayoutId = layoutId;
    }

    public String getTitle() {
        return mTitle;
    }

    private void setTitle(String title) {
        mTitle = title;
    }

    public String getMessage() {
        return mMessage;
    }

    private void setMessage(String message) {
        mMessage = message;
    }

    public int getIconId() {
        return mIconId;
    }

    private void setIconId(int iconId) {
        mIconId = iconId;
    }

    public boolean isCancelable() {
        return mCancelable;
    }

    private void setCancelable(boolean cancelable) {
        mCancelable = cancelable;
    }

    public String getPositiveText() {
        return mPositiveText;
    }

    private void setPositiveText(String positiveText) {
        mPositiveText = positiveText;
    }

    public String getNegativeText() {
        return mNegativeText;
    }

    private void setNegativeText(String negativeText) {
        mNegativeText = negativeText;
    }

    public OnPositiveListener getPositiveListener() {
        return mPositiveListener;
    }

    private void setPositiveListener(OnPositiveListener positiveListener) {
        mPositiveListener = positiveListener;
    }

    public OnNegativeListener getNegativeListener() {
        return mNegativeListener;
    }

    private void setNegativeListener(OnNegativeListener negativeListener) {
        mNegativeListener = negativeListener;
    }

    private void setContentView(View contentView) {
        mContentView = contentView;
    }
}

這里定義2個(gè)點(diǎn)擊監(jiān)聽霜第,用來(lái)回調(diào)dialog中確認(rèn)和取消的點(diǎn)擊。

/**
 * 確認(rèn)按鍵監(jiān)聽
 */
public interface OnPositiveListener {
    void onPositive(Dialog dialog);

}

/**
 * 取消按鍵監(jiān)聽
 */
public interface OnNegativeListener {
    void onNegative(Dialog dialog);
}

這里controller中封裝了最主要的代碼户辞,代碼很簡(jiǎn)單泌类,就是將上面寫的dialog的 xml布局文件inflate出來(lái)設(shè)置給dialog,這也是封裝好的默認(rèn)的dialog 就跟一開始的效果圖一樣咆课。
但是我們說(shuō)了末誓,我們有可能有其他需求扯俱,這時(shí)候就需要用builder.setcontentview將我們需要的具體的view或者layoutid傳進(jìn)來(lái),這時(shí)候看代碼喇澡,我們布局文件中的根布局ll_content就會(huì)將默認(rèn)的message的textview remove掉迅栅,然后再把傳進(jìn)來(lái)的view添加進(jìn)來(lái),這就實(shí)現(xiàn)定制其他需求的View晴玖。

private static class Controller implements View.OnClickListener,BuilderInterface {
    private Context mContext;
    private TextView mTvTitle;
    private TextView mTvMessage;
    private TextView mTvPositive;
    private TextView mTvNegative;
    private ImageView mIvIcon;
    private View mHorizontalLine;
    private View mVerticalLine;
    private View mRootView;
    private OnNegativeListener mOnNegativeListener;
    private OnPositiveListener mOnPositiveListener;
    private Dialog mDialog;
    private View mContentView;
    private final LinearLayout mLlContent;


    private   Controller(Context context) {
        mContext = context;
        mRootView = View.inflate(mContext, R.layout.view_dialog_warm_tip, null);
        mLlContent = (LinearLayout) mRootView.findViewById(R.id.ll_content);
        mHorizontalLine = mRootView.findViewById(R.id.line_horizontal);
    }

    private void setContentView(int layoutResID, Dialog dialog) {
        if (layoutResID == -1) {

        } else {
            mContentView = View.inflate(mContext, layoutResID, null);
            mLlContent.removeAllViews();
            mLlContent.addView(mContentView);
        }
        mDialog = dialog;
        dialog.setContentView(mRootView, getPrams(mContext));
    }

    private void setContentView(View view, Dialog dialog) {
        mLlContent.removeAllViews();
        mLlContent.addView(view);
        mDialog = dialog;
        dialog.setContentView(mRootView, getPrams(mContext));
    }

    private FrameLayout.LayoutParams getPrams(Context context) {
        WindowManager windowManager = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        Display sDefaultDisplay = windowManager.getDefaultDisplay();

        return new FrameLayout.LayoutParams(
                (int) (sDefaultDisplay.getWidth() * 0.80f),
                ViewGroup.LayoutParams.WRAP_CONTENT);

    }


    public Controller setTitle(String title) {
        mTvTitle = (TextView) mRootView.findViewById(R.id.title);
        if (mTvTitle != null) {
            mTvTitle.setText(title);
        }
        return this;
    }

    public Controller setMessage(String message) {
        mTvMessage = (TextView) mRootView.findViewById(R.id.message);
        if (mTvMessage != null) {
            mTvMessage.setText(message);
        }
        return this;
    }

    public Controller setIcon(int iconId) {
        mIvIcon = (ImageView) mRootView.findViewById(R.id.icon);
        if (mIvIcon != null) {
            mIvIcon.setImageResource(iconId);
            mIvIcon.setVisibility(View.VISIBLE);
        }
        return this;
    }

    @Override
    public BuilderInterface setCancelable(boolean cancelable) {
        return null;
    }


    public Controller setNegativeButton(String negativeText, OnNegativeListener listener) {
        mTvNegative = (TextView) mRootView.findViewById(R.id.dialog_cancel);
        mVerticalLine = mRootView.findViewById(R.id.line_vertical);
        if (mTvNegative != null) {
            mTvNegative.setVisibility(View.VISIBLE);
            mTvNegative.setText(negativeText);
            setOnNegativeListener(listener);
            mHorizontalLine.setVisibility(View.VISIBLE);
            if (mTvPositive != null) {
                mVerticalLine.setVisibility(View.VISIBLE);
            }

        }
        return this;
    }

    public Controller setPositiveButton(String positiveText, OnPositiveListener listener) {
        mTvPositive = (TextView) mRootView.findViewById(R.id.dialog_commit);

        if (mTvPositive != null) {
            mTvPositive.setVisibility(View.VISIBLE);
            mTvPositive.setText(positiveText);
            setOnPositiveListener(listener);
            mHorizontalLine.setVisibility(View.VISIBLE);
        }
        return this;
    }

    private Controller setOnNegativeListener(OnNegativeListener onNegativeListener) {

        mOnNegativeListener = onNegativeListener;
        mTvNegative.setOnClickListener(this);
        return this;
    }

    private Controller setOnPositiveListener(OnPositiveListener onPositiveListener) {

        mOnPositiveListener = onPositiveListener;
        mTvPositive.setOnClickListener(this);
        return this;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.dialog_cancel:
                if (mOnNegativeListener != null) {
                    mOnNegativeListener.onNegative(mDialog);
                }
                break;
            case R.id.dialog_commit:
                if (mOnPositiveListener != null) {
                    mOnPositiveListener.onPositive(mDialog);
                }
                break;
        }
    }
}

到這里dialog的封裝就完了读存,接下來(lái)看看activity中怎么使用。
使用方法就跟alertdialog一樣呕屎。

 private void initDefaultDialog() {
        SherlockDialog.Builder builder = new SherlockDialog.Builder(this);
        mDialog = builder.createDefault(this, this);
//        builder.reSetTitle("重新設(shè)置Tiltle");
    }

    private void initEditDialog() {
        SherlockDialog.Builder builder = new SherlockDialog.Builder(this);

        EditText editText = new EditText(this);
        builder.setContentView(editText);
        mDialog = builder.createDefault(this, this);

    }

    private void initDialog() {

        SherlockDialog.Builder builder = new SherlockDialog.Builder(this);
        mDialog = builder.setTitle("溫馨提示")
                .setMessage("確認(rèn)提交嗎让簿?")
                .setPositiveButton("確認(rèn)", new SherlockDialog.OnPositiveListener() {
                    @Override
                    public void onPositive(Dialog dialog) {
                        Toast.makeText(DialogActivity.this, "確認(rèn)提交", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new SherlockDialog.OnNegativeListener() {
                    @Override
                    public void onNegative(Dialog dialog) {
                        Toast.makeText(DialogActivity.this, "取消提交", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .setIcon(R.mipmap.ic_launcher_round).create();
    }

    public void button1(View view) {
        initDialog();
        mDialog.show();
    }

    public void button2(View view) {

        initEditDialog();
        mDialog.show();
    }

    public void button3(View view) {
        initDefaultDialog();
        mDialog.show();
    }

    @Override
    public void onPositive(Dialog dialog) {
        dialog.dismiss();
    }

    @Override
    public void onNegative(Dialog dialog) {
        dialog.dismiss();
    }

可以看到跟系統(tǒng)自帶的alertdialog的builder方法使用是一樣的。

githup源碼地址:
https://github.com/DarkSherlock/DialogBuilder

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秀睛,一起剝皮案震驚了整個(gè)濱河市尔当,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹂安,老刑警劉巖椭迎,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異田盈,居然都是意外死亡畜号,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門允瞧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)简软,“玉大人,你說(shuō)我怎么就攤上這事述暂”陨” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵贸典,是天一觀的道長(zhǎng)视卢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)廊驼,這世上最難降的妖魔是什么据过? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮妒挎,結(jié)果婚禮上绳锅,老公的妹妹穿的比我還像新娘。我一直安慰自己酝掩,他們只是感情好鳞芙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般原朝。 火紅的嫁衣襯著肌膚如雪驯嘱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天喳坠,我揣著相機(jī)與錄音鞠评,去河邊找鬼。 笑死壕鹉,一個(gè)胖子當(dāng)著我的面吹牛剃幌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晾浴,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼负乡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了脊凰?” 一聲冷哼從身側(cè)響起抖棘,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笙各,沒(méi)想到半個(gè)月后钉答,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杈抢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仑性。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惶楼。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖诊杆,靈堂內(nèi)的尸體忽然破棺而出歼捐,到底是詐尸還是另有隱情,我是刑警寧澤晨汹,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布豹储,位于F島的核電站,受9級(jí)特大地震影響淘这,放射性物質(zhì)發(fā)生泄漏剥扣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一铝穷、第九天 我趴在偏房一處隱蔽的房頂上張望钠怯。 院中可真熱鬧,春花似錦曙聂、人聲如沸晦炊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)断国。三九已至贤姆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稳衬,已是汗流浹背霞捡。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宋彼,地道東北人弄砍。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像输涕,于是被迫代替她去往敵國(guó)和親音婶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容