Android編程權(quán)威指南(第二版)學(xué)習(xí)筆記(十二)—— 第12章 對(duì)話框

本章主要介紹了如何使用內(nèi)嵌在 fragment 中的對(duì)話框,以及 fragment 之間如何傳遞數(shù)據(jù)

GitHub 地址:
完成第12章

1. 使用 DialogFragment

1.1 AppCompat 兼容庫

Google 推出 AppCompat 兼容庫是為了讓所有Android用戶都能體驗(yàn)到新特性。AppCompat兼容庫能通過支持庫的方式將部分最新系統(tǒng)的特色功能移植到Android舊版本系統(tǒng)中。

應(yīng)該在 Porject Structure 中添加 appcompat-v7 的依賴。

1.2 創(chuàng)建 DialogFragment

建議將 AlertDialog 封裝在 DialogFragment (Fragment的子類)實(shí)例中使用。當(dāng)然,不使用DialogFragment 也可顯示 AlertDialog 視圖,但不推薦這樣做。使用 FragmentManager 管理對(duì)話框,可以更靈活地顯示對(duì)話框。

如果旋轉(zhuǎn)設(shè)備,單獨(dú)使用的 AlertDialog 會(huì)消失,而封裝在 fragment 中的 AlertDialog 則不會(huì)有此問題(旋轉(zhuǎn)后,對(duì)話框會(huì)被重建恢復(fù))。

  • 首先需要一個(gè)針對(duì) dialog 的布局文件,如 DatePicker 作為根元素的 Dialog 用于選擇日期。
<?xml version="1.0" encoding="utf-8"?>
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_date_date_picker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:calendarViewShown="false">
    <!--舊版系統(tǒng)會(huì)使用 calenderViewShown 屬性-->

</DatePicker>
  • 然后新建一個(gè)父類是 DialogFragment 的類 DatePickerFragment,重寫其中的 onCreateDialog 方法,返回一個(gè)AlertDialog
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // 使用 LayoutInflater 引用布局文件創(chuàng)建用于顯示 Dialog 的 View
    View v = LayoutInflater.from(getActivity())
                .inflate(R.layout.dialog_date, null);
                
    return new AlertDialog.Builder(getActivity())
        .setView(v) // 設(shè)置視圖
        .setTitle(R.string.date_picker_title) //設(shè)置標(biāo)題
        // 設(shè)置 OK 按鈕,OnClickListener 暫時(shí)留空
        .setPositiveButton(android.R.string.ok, null)
        // 使用 Builder 的 create() 方法創(chuàng)建 Dialog 并返回
        .create(); 
}

在使用 DialogFragment 時(shí),使用成員方法 show 來顯示 dialog:

// 在 Fragment 中為 DatePickerFragment 添加一個(gè) Tag
private static final String DIALOG_DATE = "DialogDate";
……
// 在 Fragment 內(nèi)部獲取 FragmentManager
FragmentManager manager = getFragmentManager(); 
DatePickerFragment dialog = new DatePickerFragment();
// 顯示對(duì)話框
dialog.show(manager, DIALOG_DATE);

2. fragment 之間的數(shù)據(jù)傳遞

我們之前實(shí)現(xiàn)了 activity 之間以及基于 fragment 的 activity 之間的數(shù)據(jù)傳遞?,F(xiàn)在需實(shí)現(xiàn)同一 activity 托管的兩個(gè) fragment 之間的數(shù)據(jù)傳遞。


一個(gè) activity 托管的不同 fragment 之間數(shù)據(jù)的傳遞

2.1 將數(shù)據(jù)傳遞到對(duì)話框

顯然,要達(dá)到目的,只需要在 DatePickerFragment 中建立獲取實(shí)例的 newInstance 方法,其中需要的參數(shù)是傳遞的信息即可,示例如下

// DatePickerFragment.java

public static DatePickerFragment newInstance(Date date) {
    // 新建一個(gè) Bundle 對(duì)象用于存放數(shù)據(jù)
    Bundle args = new Bundle();
    args.putSerializable(ARG_DATE, date);
    DatePickerFragment fragment = new DatePickerFragment();
    // 使用 fragment arguments 來傳遞參數(shù)
    fragment.setArguments(args);
    return fragment;
}

記得把使用 DatePickerFragment 的構(gòu)造方法的地方改成 newInstance 方法獲取實(shí)例。

在獲得數(shù)據(jù)之后,要先將 DatePicker 初始化為原本的日期,首先用 Fragment 的 getArguments().getSeriallizable(String key) 方法獲取數(shù)據(jù),然后用 Calendar 對(duì)象取出 date 中的年月日,最后使用 DatePicker 類的 init(int year, int month, int dayOfMonth, OnDateChangedListener listener) 方法 初始化默認(rèn)日期

2.2 從對(duì)話框回傳數(shù)據(jù)

2.2.1 設(shè)置目標(biāo) fragment

類似于 activity 間的關(guān)聯(lián),可將 CrimeFragment 設(shè)置成 DatePickerFragment 的目標(biāo) fragment。 即使是在 CrimeFragment 和 DatePickerFragment 被銷毀和重建后,操作系統(tǒng)也會(huì)重新關(guān)聯(lián)它們。調(diào)用以下 Fragment 方法可建立這種關(guān)聯(lián):

public void setTargetFragment(Fragment fragment, int requestCode)

該方法有兩個(gè)參數(shù):目標(biāo) fragment 以及請(qǐng)求代碼。需要時(shí),目標(biāo) fragment 使用請(qǐng)求代碼確認(rèn)是哪個(gè) fragment 在回傳數(shù)據(jù)。

目標(biāo) fragment 和請(qǐng)求代碼由 FragmentManager 負(fù)責(zé)跟蹤管理,我們可調(diào)用設(shè)置目標(biāo)的 fragment 的 getTargetFragment()getTargetRequestCode() 方法獲取它們。

2.2.2 傳遞數(shù)據(jù)給目標(biāo) Fragment

處理由同一 activity 托管的兩個(gè) fragment 間的數(shù)據(jù)返回時(shí),可借用Fragment.onActivityResult(...)方法。因此,直接調(diào)用目標(biāo) fragment 的Fragment.onActivityResult(...)方法,,就能實(shí)現(xiàn)數(shù)據(jù)的回傳。該方法恰好有我們需要的如下信息:

  • 請(qǐng)求代碼:與傳入setTargetFragment(...)方法相匹配,告訴目標(biāo) fragment 返回結(jié)果來 自哪里。
  • 結(jié)果代碼:決定下一步該采取什么行動(dòng)。
  • Intent:包含 extra 數(shù)據(jù)。

所以從 CrimeFragment 中顯示 DatePickerFragment,用戶選擇日期以后,想要回傳信息,可以寫一個(gè) sendResult 方法,該方法如下:

// DatePickerFragment.java

public static final String EXTRA_DATE =
    "com.kniost.criminalintent.date";
 ……                
private void sendResult(int resultCode, Date date) {
    // 防止出錯(cuò)
    if (getTargetFragment() == null) {
        return; 
    }
    Intent intent = new Intent();
    // 放置數(shù)據(jù)到 Intent 中
    intent.putExtra(EXTRA_DATE, date);
    // 獲取目標(biāo) fragment,調(diào)用其 onActivityResult 方法,其中 RequestCode 是用 getTargetRequestCode 方法獲取的,resultCode 是傳入?yún)?shù),intent 包含了數(shù)據(jù)
    getTargetFragment()
        .onActivityResult(getTargetRequestCode(), resultCode, intent);
}

在 CrimeFragment 中則應(yīng)該重寫 onActivityResult 方法:

// CrimeFragment.java

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // 如果一切正常,調(diào)用 sendResult 的方法時(shí)傳入的參數(shù)應(yīng)該就是 Activity.RESULT_OK,所以不會(huì)直接 return
    if (resultCode != Activity.RESULT_OK) {
        return;
    }
    
    // 如此判斷方便有多個(gè)回傳時(shí)使用
    if (requestCode == REQUEST_DATE) {
        Date date = (Date) data
            .getSerializableExtra(DatePickerFragment.EXTRA_DATE);
        mCrime.setDate(date); mDateButton.setText(mCrime.getDate().toString());
    }
}

3. 挑戰(zhàn)練習(xí)

//待完成


GitHub Page: kniost.github.io
簡書:http://www.itdecent.cn/u/723da691aa42

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,138評(píng)論 25 708
  • Jedis是java語言實(shí)現(xiàn)的Redis客戶端驅(qū)動(dòng)。Data Redis的封裝并不太必要,因?yàn)镴edis已足夠簡單...
    zhanglbjames閱讀 1,777評(píng)論 1 1
  • 暈車復(fù)暈車, 日日都沒喝。 長嘯且徐行, 我行亦我歌。
    遷于喬木閱讀 200評(píng)論 0 0
  • 如果可以擁抱 那就 別只顧著握手寒暄 因?yàn)?黑夜很長 冬天很冷 如果可以多給祝福 那就 請(qǐng)少給建議 因?yàn)?奔跑的路...
    老草閱讀 209評(píng)論 1 1
  • 對(duì)于世界. 可能我只是一個(gè)人! 但對(duì)于某個(gè)人.曾經(jīng)的我是他的整個(gè)世界!
    Ring_my_bell閱讀 196評(píng)論 0 1

友情鏈接更多精彩內(nèi)容