tgr*_*ger 5 android android-fragments android-fragmentactivity
我正在尝试使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
其中一个细节片段的示例.在不同的情况下可以创建许多不同的片段.
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());
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
在电话上时,使用包装器活动来保存片段
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 {
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,更改详细信息窗格中打开的片段的正确方法是什么?我的方法在使用两个窗格时感觉像是一个黑客,并且在仅使用一个窗格时甚至不起作用,因为getParent()
从SinglePaneFragmentWrapper返回null,使我无法调用parent.changeDetailFragment()
.
这是一个复杂的问题,希望我能很好地解释.如果我错过了什么,请告诉我.谢谢
对此有很多观点,也有很多实现方法。我认为在这种情况下,问题是“谁负责更改片段?” 从表面上看,按钮上的侦听器似乎是明显的地方,但是片段不应该知道它托管在什么中(其症状是从 getParent() 获得像 null 这样的不良结果)。
在你的情况下,我建议你在父级中实现一个“监听器”接口,并从片段中“通知”。当通知父级时,它会更改片段。这样片段就不会改变自身(所以不需要知道如何改变)..所以..对于你的情况..
添加新接口:
public interface FragmentChangeListener {
void onFragmentChangeRequested(Fragment newFragment);
}
Run Code Online (Sandbox Code Playgroud)
在 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);
}
}
Run Code Online (Sandbox Code Playgroud)
添加监听器到详细片段
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
并对您的单窗格活动实现相同的界面...
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);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意单窗格和多窗格活动之间的相似性。这表明您可以将所有重复的代码(更改片段等)放入它们都扩展的单个活动中,或者它们可能是具有不同功能的相同活动布局...
我希望这有帮助,祝你好运。
问候,CJ
归档时间: |
|
查看次数: |
1654 次 |
最近记录: |