[英]Switching Fragments in Master/Detail Flow
我正在嘗試創建一個使用Fragments具有Master / Detail流程的應用程序。 選擇一個項目將打開一個細節片段,然后可以“打開”另一個片段並將其添加到后台堆棧。
我已經重命名了類來幫助說明他們的工作。
public class ListOfDetails extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
//Callback method indicating that an item with the given ID was selected.
public void onItemSelected(String id) {
// Performing logic to determine what fragment to start omitted
if (ifTwoPanes()) {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
Intent newIntent = new Intent(this, SinglePaneFragmentWrapper.class);
newIntent.putExtra("id", id);
startActivity(newIntent);
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
}
其中一個細節片段的示例。 可以在不同情況下創建許多不同的片段。
public class DetailFragmentType1 extends Fragment {
private ListOfDetails parent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity a = getActivity();
if (a instanceof ListOfDetails) {
parent = (ListOfDetails) a;
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button aButton = (Button) getActivity().findViewById(R.id.aButton);
aButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.changeDetailFragment(new SubDetailFragment());
}
});
}
}
在電話上時,使用包裝器活動來保存片段
public class SinglePaneFragmentWrapper extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Duplicate logic must be performed to start fragment
// Performing logic to determine what fragment to start omitted
String id = getIntent().getStringExtra("id");
if(id == "DetailFragmentType1") {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
...
}
}
}
在這種情況下,更改詳細信息窗格中打開的片段的正確方法是什么? 我的方法在使用兩個窗格時感覺像是一個黑客,並且在僅使用一個窗格時甚至不起作用,因為SinglePaneFragmentWrapper中的getParent()
返回null,使我無法調用parent.changeDetailFragment()
。
這是一個復雜的問題,希望我能很好地解釋。 如果我錯過了什么,請告訴我。 謝謝
圍繞這個有很多意見,有很多方法可以做到這一點。 我認為在這種情況下,問題是“誰負責更改片段?” 從表面上看,按鈕上的監聽器似乎是顯而易見的地方,但是片段不應該知道它所托管的內容(這種情況的一個症狀是從getParent()獲得一個不合理的結果,如null)。
在您的情況下,我建議您在父級中實現“偵聽器”接口,並從片段中“通知”..當通知父級時,它會更改片段。 這樣片段本身不會改變(所以不需要知道如何)..所以...對於你的情況..
添加新界面:
public interface FragmentChangeListener {
void onFragmentChangeRequested(Fragment newFragment);
}
在ListOfDetails活動中實現接口
public class ListOfDetails extends FragmentActivity implements FragmentChangeListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
//Callback method indicating that an item with the given ID was selected.
public void onItemSelected(String id) {
// Performing logic to determine what fragment to start omitted
if (ifTwoPanes()) {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
Intent newIntent = new Intent(this, SinglePaneFragmentWrapper.class);
newIntent.putExtra("id", id);
startActivity(newIntent);
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
// This is the interface implementation that will be called by your fragments
void onFragmentChangeRequested(Fragment newFragment) {
changeDetailFragment(newFragment);
}
}
添加了詳細信息片段的監聽器
public class DetailFragmentType1 extends Fragment {
private FragmentChangeListener fragmentChangeListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Actually you might not have an activity here.. you should probably be
// doing this in onAttach
//Activity a = getActivity();
//if (a instanceof ListOfDetails) {
// parent = (ListOfDetails) a;
//}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button aButton = (Button) getActivity().findViewById(R.id.aButton);
aButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// parent.changeDetailFragment(new SubDetailFragment());
notifyFragmentChange(new SubDetailFragment());
}
});
}
@Override
public void onAttach(Activity activity) {
// This is called when the fragment is attached to an activity..
if (activity instanceof FragmentChangeListener) {
fragmentChangeListener = (FragmentChangeListener) activity;
} else {
// Find your bugs early by making them clear when you can...
if (BuildConfig.DEBUG) {
throw new IllegalArgumentException("Fragment hosts must implement FragmentChangeListener");
}
}
}
private void notifyFragmentChange(Fragment newFragment) {
FragmentChangeListener listener = fragmentChangeListener;
if (listener != null) {
listener.onFragmentChangeRequested(newFragment);
}
}
}
並為您的單一窗格活動實現相同的界面......
public class SinglePaneFragmentWrapper extends FragmentActivity implements FragmentChangeListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Duplicate logic must be performed to start fragment
// Performing logic to determine what fragment to start omitted
String id = getIntent().getStringExtra("id");
if(id == "DetailFragmentType1") {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
...
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
// This is the interface implementation that will be called by your fragments
void onFragmentChangeRequested(Fragment newFragment) {
changeDetailFragment(newFragment);
}
}
請注意單個窗格和多窗格活動之間的相似性。這表明您可以將所有重復的代碼(changefragment等)放入一個它們都擴展的活動中,或者可能是相同的活動布局...
祝希望有所幫助,祝你好運。
此致,CJ
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.