Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 詳解Android應用中DialogFragment的基本用法

詳解Android應用中DialogFragment的基本用法

編輯:關於Android編程

DialogFragment的基本用法
1. 創建DialogFragment

public class DialogA extends DialogFragment implements DialogInterface.OnClickListener {

 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
  builder.setMessage(R.string.dialoga_title)
    .setPositiveButton(R.string.ok, this)
    .setNegativeButton(R.string.cancel, this);

  return builder.create();
 } 

 @Override
 public void onClick(DialogInterface dialog, int id) {
  switch(id) {
   case AlertDialog.BUTTON_NEGATIVE:
    Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
    break;
   case AlertDialog.BUTTON_POSITIVE:
    Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
    break;
   default:
    break;
  } 
 } 
}

說明:自定義一個DialogFragment,並重寫它的onCreateDialog()方法。
2. 調用該DialogFragment
下面是在FragmentActivity中調用該DialogFragment對話框。

public class DialogTest extends FragmentActivity {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  showDialog();
 }

 private void showDialog() {
  FragmentManager fm = getSupportFragmentManager();
  DialogA dialoga = new DialogA();
  dialoga.show(fm, "fragmenta");
 }
}

自定義DialogFragment布局
下面介紹自定義DialogFragment的布局的方法
點擊查看:自定義DialogFragment布局的完整代碼
1. 設置布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical" >

 <TextView
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/dialoga_intro" />

 <ImageView
  android:id="@+id/image"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/ic_action_video" />

</LinearLayout>

2. 使用布局

public class DialogA extends DialogFragment implements DialogInterface.OnClickListener {

 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
  LayoutInflater inflater = getActivity().getLayoutInflater();
  builder.setView(inflater.inflate(R.layout.dialoga, null))
    .setMessage(R.string.dialoga_title)
    .setPositiveButton(R.string.ok, this)
    .setNegativeButton(R.string.cancel, this);

  return builder.create();
 }

 @Override
 public void onClick(DialogInterface dialog, int id) {
  switch(id) {
   case AlertDialog.BUTTON_NEGATIVE:
    Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
    break;
   case AlertDialog.BUTTON_POSITIVE:
    Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
    break;
   default:
    break;
  }
 }
}

DialogFragment和Activity的交互
下面介紹自定義DialogFragment和Activity交互的方法
點擊查看:DialogFragment和Activity交互的完整代碼
1. 定義通信接口
在DialogFragment中定義它們之間的通信接口。

public interface NoticeDialogListener {
 public void onDialogPositiveClick(DialogFragment dialog);
 public void onDialogNegativeClick(DialogFragment dialog);
} 

// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;

// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
@Override
public void onAttach(Activity activity) {
 super.onAttach(activity);
 // Verify that the host activity implements the callback interface
 try {
  // Instantiate the NoticeDialogListener so we can send events to the host
  mListener = (NoticeDialogListener) activity;
 } catch (ClassCastException e) {
  // The activity doesn't implement the interface, throw exception
  throw new ClassCastException(activity.toString()
    + " must implement NoticeDialogListener");
 } 
} 

2. 在DialogFragment中調用該接口

@Override
public void onClick(DialogInterface dialog, int id) {
 switch(id) {
  case AlertDialog.BUTTON_POSITIVE:
   //Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
   mListener.onDialogPositiveClick(DialogA.this);
   break;
  case AlertDialog.BUTTON_NEGATIVE:
   //Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
   mListener.onDialogNegativeClick(DialogA.this);
   break;
  default:
   break;
 } 
}

3. 在Activity中實現該接口

public class DialogTest extends FragmentActivity 
 implements DialogA.NoticeDialogListener {

 ...

 @Override
 public void onDialogPositiveClick(DialogFragment dialog) {
  Toast.makeText(this, "Positive Callback", Toast.LENGTH_SHORT).show();
 }
 @Override
 public void onDialogNegativeClick(DialogFragment dialog) {
  Toast.makeText(this, "Negative Callback", Toast.LENGTH_SHORT).show();
 }
}

Dialog與DialogFragment的對比
從代碼的編寫角度看,Dialog使用起來要更為簡單,但是Google則是推薦盡量使用DialogFragment(對於Android 3.0以下的版本,可以結合使用support包中提供的DialogFragment以及FragmentActivity)。今天試著用這兩種方式來創建對話框,發現DialogFragment果然有一個非常好的特性(在手機配置變化,導致Activity需要重新創建時,例如旋屏,基於DialogFragment的對話框將會由FragmentManager自動重建,然而基於Dialog實現的對話框則沒有這樣的能力)。

下面是兩段實例代碼:

他們使用的界面都一樣:(dialog.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >
 
 <ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/ic_launcher" />
 
</LinearLayout>

1.基於Dialog實現的對話框

public class MainActivity extends Activity {
 private Button clk;
 private Dialog dialog;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  dialog = new Dialog(this);
  dialog.setContentView(R.layout.dialog);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    dialog.show();
   }
  });
 }
}

當我們點擊按鈕時,會彈出對話框(內容為android logo),當我們旋轉屏幕後,Activity重新創建,整個Activity的界面沒有問題,而對話框消失了。
除此之外,其實還有一個問題,就是在logcat中會看到異常信息:Android..leaked .. window,這是因為在Activity結束之前,Android要求所有的Dialog必須要關閉。我們旋屏後,Activity會被重建,而上面的代碼邏輯並沒有考慮到對話框的狀態以及是否已關閉。

於是將上述代碼修改為:

public class MainActivity extends Activity {
 private Button clk;
 private Dialog dialog;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  dialog = new Dialog(this);
  dialog.setContentView(R.layout.dialog);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    dialog.show();
   }
  });
 
  //用戶恢復對話框的狀態
  if(savedInstanceState != null && savedInstanceState.getBoolean("dialog_show"))
   clk.performClick();
 }
 
 /**
  * 用於保存對話框的狀態以便恢復
  */
 @Override
 protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  if(dialog != null && dialog.isShowing())
   outState.putBoolean("dialog_show", true);
  else
   outState.putBoolean("dialog_show", false);
 }
 
 /**
  * 在Activity銷毀之前,確保對話框以關閉
  */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(dialog != null && dialog.isShowing())
   dialog.dismiss();
 }
}


2. 基於DialogFragment的對話框

與上面的對話框使用同樣的界面布局,此處僅僅展現一個簡單對話框,因此只重寫了onCreateView方法

public class MyDialogFragment extends DialogFragment {
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View v = inflater.inflate(R.layout.dialog, container, false);
  return v;
 }
}

public class MainActivity extends FragmentActivity {
 private Button clk;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    MyDialogFragment mdf = new MyDialogFragment();
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    mdf.show(ft, "df");
   }
  });
 }
}


這兩段代碼可以實現第一種方式的同樣功能,此處我們並沒有去關心對話框的重建,以及Activity銷毀前對話框是否已關閉,這一切都是由FragmentManager來管理。
其實DialogFragment還擁有fragment的優點,即可以在一個Activity內部實現回退(因為FragmentManager會管理一個回退棧)

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved