今天我將要講的是fragment間的數據是如何進行傳遞的。這裡我將舉個簡單的例子。 首先要有個MainActivity,它托管了MainFragment,而MainFragment又托管了DatePickerFragment。其間用到了簡單的模型Crime,它只有Date類型的mDate一個屬性。例 ...
今天我將要講的是fragment間的數據是如何進行傳遞的。這裡我將舉個簡單的例子。
首先要有個MainActivity,它托管了MainFragment,而MainFragment又托管了DatePickerFragment。其間用到了簡單的模型Crime,它只有Date類型的mDate一個屬性。例子中的關註點是日期怎麼在MainFragment和DatePickerFragment間傳遞的。
1.調整佈局
strings.xml添加字元串資源
<resources>
<string name="app_name">mytest</string>
<string name="date_picker_title">Date of crime:</string> <!--添加這一行-->
</resources>
activity_main.xml添加FrameLayout佈局
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mytest.MainActivity">
</FrameLayout>
fragment_main.xml中添加button組件
<Button
android:id="@+id/crime_data"
android:text="初始時間"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
dialog_date.xml添加DatePicker組件
<DatePicker
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false">
</DatePicker>
2.Crime.java
public class Crime {
private Date mDate;
public Crime() {
mDate=new Date();
}
public Date getDate() {
return mDate;
}
public void setDate(Date date) {
mDate = date;
}
}
3. MainFragment.java
繼承Fragment,在onCreateView方法中創建並配置fragment視圖,其間設置按鈕的監聽事件,點擊後,調用DatePickerFragment的靜態函數newInstance,將數據保存在argument bundle中,並同時設置DatePickerFragment的目標fragment是MainFragment。最後設置對於DatePicker對話框的響應。
package com.example.mytest;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import java.util.Date;
public class MainFragment extends Fragment {
private Crime mCrime;
private Button mDateButton;
private static final String DIALOG_DATE="DialogDate";
private static final int REQUEST_DATE=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrime=new Crime();
}
//創建和配置fragment視圖
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,
Bundle savedInstanceState) {
//載入佈局
View v=inflater.inflate(R.layout.fragment_main,container,false);
//生成並使用組件
mDateButton=(Button)v.findViewById(R.id.crime_data);
mDateButton.setText(mCrime.getDate().toString());
//mDateButton.setEnabled(false);
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager=getFragmentManager();
//newInstance替換構造方法
//DatePickerFragment dialog=new DatePickerFragment();
DatePickerFragment dialog=DatePickerFragment.newInstance(mCrime.getDate());
//設置目標fragment
dialog.setTargetFragment(MainFragment.this,REQUEST_DATE);
dialog.show(manager,DIALOG_DATE); //顯示DialogFragment
}
});
return v;
}
//響應DatePicker對話框
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode!= Activity.RESULT_OK){
return;
}
if (requestCode==REQUEST_DATE){
Date date=(Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
mDateButton.setText(mCrime.getDate().toString());
}
super.onActivityResult(requestCode, resultCode, data);
}
}
4.DatePickerFragment.java
直接獲取保存在arguments中的數據,並將數據顯示,最後設置目標fragment。
package com.example.mytest;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class DatePickerFragment extends DialogFragment{
private static final String ARG_DATE="date";
public static final String EXTRA_DATE= "com.example.mytest.date";
private DatePicker mDatePicker;
//便於被調用傳遞數據給DatePickerFragment
//保存日期到argument bundle中,便於DatePickerFragment直接獲取
public static DatePickerFragment newInstance(Date date){
Bundle args=new Bundle();
args.putSerializable(ARG_DATE,date);
DatePickerFragment fragment=new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//獲取Date對象並初始化DatePicker
Date date=(Date)getArguments().getSerializable(ARG_DATE);
Calendar calendar=Calendar.getInstance();
calendar.setTime(date);
int year=calendar.get(Calendar.YEAR);
int month=calendar.get(Calendar.MONTH);
int day=calendar.get(Calendar.DAY_OF_MONTH);
//添加DatePicker
View v=LayoutInflater.from(getActivity())
.inflate(R.layout.dialog_date,null);
mDatePicker=(DatePicker)v.findViewById(R.id.dialog_date_picker);
mDatePicker.init(year,month,day,null);
return new AlertDialog.Builder(getActivity())
.setView(v)
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int year=mDatePicker.getYear();
int month=mDatePicker.getMonth();
int day=mDatePicker.getDayOfMonth();
Date date=new GregorianCalendar(year,month,day).getTime();
sendResult(Activity.RESULT_OK,date);
}
})
.create();
}
//回調目標fragment
private void sendResult(int resultCode,Date date){
if (getTargetFragment()==null){
return;
}
Intent intent=new Intent();
intent.putExtra(EXTRA_DATE,date);
getTargetFragment().onActivityResult(getTargetRequestCode(),resultCode,intent);
}
}
5.MainActivity.java
托管MainFragment,使界面呈現出來。
package com.example.mytest;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm=getSupportFragmentManager();
Fragment fragment=fm.findFragmentById(R.id.fragment_container);
if (fragment==null){
fragment=new MainFragment();
fm.beginTransaction()
.add(R.id.fragment_container,fragment)
.commit();
}
}
}
6.運行結果如下。
註意現在的時間點
點擊按鈕
更改一下時間點
按鈕ok後時間改變了!
7.總結一下
1. 傳遞數據給DatePickerFragment
- 要傳遞crime日期給DatePickerFragment,需將它保存在DatePickerFragment的argument bundle中。
這樣,DatePickerFragment就能直接獲取它。 - 創建和設置fragment argument通常是在newInstance()方法中完成的(代替fragment構造方法)。
2. 返回數據給MainFragment
- 設置目標fragment。
類似於activity間的關聯,可將MainFragment設置成DatePickerFragment的目標fragment。這樣,在MainFragment和DatePickerFragment被銷毀並重建後,操作系統會重新關聯它們。
調用以下方法可建立這種關聯:
public void setTargetFragment(Fragment fragment,int requestCode)
- 傳遞數據給目標fragment
建立MainFragment與DatePickerFragment之間的聯繫後,需要將數據回傳給MainFragment。回傳日期將作為extra附加給Intent。