DialogFragment實(shí)現(xiàn)底部彈窗

歡迎Follow我的GitHub, 關(guān)注我的簡書. 其余參考Android目錄.

Bottom Dialog

本文的合集已經(jīng)編著成書,高級Android開發(fā)強(qiáng)化實(shí)戰(zhàn)蜕劝,歡迎各位讀友的建議和指導(dǎo)檀头。在京東即可購買:https://item.jd.com/12385680.html

Android

Android對于底部彈窗已經(jīng)在23.2新的實(shí)現(xiàn)方式, 即BottomSheet. 然而對于低版本, 我們?nèi)孕枋褂?strong>DialogFragment. 底部彈窗與普通Dialog不同, 需要緊貼應(yīng)用下部, 但本質(zhì)仍是一個(gè)Fragment, 通過繼承DialogFragment類, 定制不同樣式的Fragment.

本文源碼的GitHub下載地址

定制DialogFragment

底部彈窗, 需要緊貼應(yīng)用下部. 設(shè)置Dialog樣式(Style), 全屏/布局/外部取消. 設(shè)置Dialog位置(LayoutParams), 底部/寬度最大.

@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // 使用不帶Theme的構(gòu)造器, 獲得的dialog邊框距離屏幕仍有幾毫米的縫隙。
    Dialog dialog = new Dialog(getActivity(), R.style.BottomDialog);

    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // 設(shè)置Content前設(shè)定
    dialog.setContentView(R.layout.fragment_bottom);
    dialog.setCanceledOnTouchOutside(true); // 外部點(diǎn)擊取消

    // 設(shè)置寬度為屏寬, 靠近屏幕底部岖沛。
    Window window = dialog.getWindow();
    WindowManager.LayoutParams lp = window.getAttributes();
    lp.gravity = Gravity.BOTTOM; // 緊貼底部
    lp.width = WindowManager.LayoutParams.MATCH_PARENT; // 寬度持平
    window.setAttributes(lp);

    ButterKnife.bind(this, dialog); // Dialog即View

    initClickTypes();

    return dialog;
}

ButterKnife綁定View, 但是Layout布局在Dialog初始化中設(shè)置, 所以選擇綁定Dialog, 因?yàn)槎祭^承自View.

Dialog的樣式. 寬度最大, 高度匹配, 是否浮現(xiàn)于Activity之上, 關(guān)閉背景暗色.

<style name="BottomDialog" parent="@style/AppTheme">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>

控制邏輯

初始化控件組, 把圖片\文字\框架組成三個(gè)控件組; 初始化框架點(diǎn)擊事件, 點(diǎn)擊不同的框架, 替換文字顏色與選中圖片. 點(diǎn)擊發(fā)送按鈕mTvSend, 根據(jù)當(dāng)前選中狀態(tài), 動態(tài)更新金幣.

private void initClickTypes() {
    initViewArray(); // 初始化控件組
    initLayout(); // 初始化框架點(diǎn)擊事件
    
    mTvSend.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            String typeStr = "金幣不足";
            switch (mType) {
                case 0:
                    if (countCoins(100))
                        typeStr = "一字之師";
                    break;
                case 1:
                    if (countCoins(200))
                        typeStr = "妙語連珠";
                    break;
                case 2:
                    if (countCoins(800))
                        typeStr = "學(xué)識豐富";
                    break;
                case 3:
                    if (countCoins(1200))
                        typeStr = "博學(xué)多才";
                    break;
                default:
                    break;
            }
            Toast.makeText(getContext(), typeStr, Toast.LENGTH_SHORT).show();
        }
    });
}

初始化控件組, 框架, 文字與圖片.

private void initViewArray() {
    mLayouts = new ArrayList<>();
    mTvTypes = new ArrayList<>();
    mIvTypes = new ArrayList<>();

    mLayouts.add(mLlFirstContainer);
    mLayouts.add(mLlSecondContainer);
    mLayouts.add(mLlThirdContainer);
    mLayouts.add(mLlForthContainer);

    mTvTypes.add(mTv100Coins);
    mTvTypes.add(mTv2Yuan);
    mTvTypes.add(mTv8Yuan);
    mTvTypes.add(mTv12Yuan);

    mIvTypes.add(mIv100Coins);
    mIvTypes.add(mIv2Yuan);
    mIvTypes.add(mIv8Yuan);
    mIvTypes.add(mIv12Yuan);
}

Tv代表TextView的縮寫, Iv代表ImageView的縮寫.

初始化布局的點(diǎn)擊事件. 點(diǎn)擊不同布局, 選擇不同類型. mType保存當(dāng)前選中的類型.

private void initLayout() {
    chooseRegardsType(mType); // 選擇默認(rèn)類型

    for (int i = 0; i < mLayouts.size(); i++) {
        final int tmp = i;
        LinearLayout ll = mLayouts.get(i);
        ll.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                mType = tmp;
                chooseRegardsType(mType);
            }
        });
    }
}

選擇類型, 根據(jù)選擇類型, 設(shè)置狀態(tài), 通過狀態(tài)控制

private void chooseRegardsType(int type) {
    int size = mTvTypes.size();
    for (int i = 0; i < size; ++i) {
        if (i != type) {
            mTvTypes.get(i).setEnabled(true);
            mIvTypes.get(i).setEnabled(true);
        } else {
            mTvTypes.get(i).setEnabled(false);
            mIvTypes.get(i).setEnabled(false);
        }
    }
}

例如, Text文字的顏色, 隨著狀態(tài)改變.

android:textColor="@color/regard_text_bkg"

默認(rèn)是灰色, 選中enable是false, 顏色是白色.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#848484" android:state_enabled="true"/>
    <item android:color="#FFFFFF" android:state_enabled="false"/>
</selector>

啟動Dialog

通過FragmentManager, 使用DialogFragment的show方法, 顯示Dialog.

public void showBottomDialog(View view) {
    FragmentManager fm = getSupportFragmentManager();
    BottomDialogFragment editNameDialog = new BottomDialogFragment();
    editNameDialog.show(fm, "fragment_bottom_dialog");
}

效果

動畫

在DialogFragment中, 定制布局樣式, 處理邏輯關(guān)系, 使用FragmentManager控制并顯示Dialog, 實(shí)現(xiàn)經(jīng)典的底部彈窗樣式.

OK, that's all! Enjoy it!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末暑始,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子婴削,更是在濱河造成了極大的恐慌廊镜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唉俗,死亡現(xiàn)場離奇詭異嗤朴,居然都是意外死亡配椭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門雹姊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來股缸,“玉大人,你說我怎么就攤上這事吱雏《匾觯” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵坎背,是天一觀的道長替劈。 經(jīng)常有香客問我,道長得滤,這世上最難降的妖魔是什么陨献? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮懂更,結(jié)果婚禮上眨业,老公的妹妹穿的比我還像新娘。我一直安慰自己沮协,他們只是感情好龄捡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著慷暂,像睡著了一般聘殖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上行瑞,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天奸腺,我揣著相機(jī)與錄音,去河邊找鬼血久。 笑死突照,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氧吐。 我是一名探鬼主播讹蘑,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼筑舅!你這毒婦竟也來了座慰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤翠拣,失蹤者是張志新(化名)和其女友劉穎角骤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邦尊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年背桐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝉揍。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡链峭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出又沾,到底是詐尸還是另有隱情弊仪,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布杖刷,位于F島的核電站励饵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滑燃。R本人自食惡果不足惜役听,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望表窘。 院中可真熱鬧典予,春花似錦、人聲如沸乐严。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昂验。三九已至捂敌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間既琴,已是汗流浹背黍匾。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呛梆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓磕诊,卻偏偏與公主長得像填物,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子霎终,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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