针对这种设计风格,没有固定方法,因为它不被鼓励。然而,我找到了一种方法使其正常工作:您需要手动设计您的导航菜单。
您的应用程序应该有一个活动(Activity),即FragmentActivity。它具有一个FragmentTabHost来容纳每个TabFragments(选项卡碎片)。
TabFragment是我创建的抽象类,用于代表TabSpec中的选项卡。它将管理选项卡内部的导航和碎片切换。
然后,您创建的各个碎片可以在TabFragment对象内进行切换。以下是代码:
活动(Activity)
public class MainActivity extends FragmentActivity {
private FragmentTabHost tabHost;
//(TabFragment)s will set this property when created so the Activity can communicate with it
public TabFragment activeFragment;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//create tabHost based on .xml layout
tabHost = (FragmentTabHost)findViewById(R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);
//add each of your tabs to the tabHost. These are all (TabFragment)s
tabHost.addTab(tabHost.newTabSpec("New Tab").setIndicator("New Tab"),
ExampleTabFragment.class, null);
}
/*override the onBackPressed method, so that your application does not close every
time the user navigates back. Instead, calls the activeFragment to determine behavior*/
@Override
public void onBackPressed() {
activeFragment.onBackPressed();
}
//method for TabFragment to call when the user navigates out of the app
public void close(){
super.onBackPressed();
}
}
TabFragment
public abstract class TabFragment extends Fragment {
@Override
public void onResume(){
//sets the property in the Activity so we can reference this from it.
((MainActivity) getActivity()).activeFragment=this;
super.onResume();
}
//this will be the method called when the back button is pressed. It will navigate.
public abstract void onBackPressed();
}
TabFragment的实例
在TabFragment的实例中应该有一个FrameLayout,可以将子Fragments附加到其中。第一次点击选项卡时,它将启动在onCreate()
中指定的Fragment。从另一个选项卡切换回来后,它将恢复上次显示的任何Fragment。如果需要进行分层导航,则应使用onBackPressed()方法返回到前面的Fragments。我使用了一个字节属性(tabContentIndex
)来确定如何导航。如果添加一个以此TabFragment实例为参数的构造函数,Fragments可以互相交换。它们将通过访问start(Example)Fragment()
方法来实现这一点。请记住,“返回”按钮最终必须退出应用程序。
public class NewTrailTabContent extends TabFragment {
//to determine what child Fragment is active
byte tabContentIndex;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//a simple FrameLayout in this case. Child Fragments will be attached.
return inflater.inflate(R.layout.example_fragment, container,
false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
//The tab starts with this Fragment
startDiologFragment();
super.onCreate(savedInstanceState);
}
public void startExampleFragment(){
/*Fragment's constructor allows us to reference the parent to navigate. In effect, this
Fragment will be able to call these navigation methods.*/
ExampleFragment newFragment = new ExampleFragment(this);
FragmentManager fragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
//this Resource is the FrameLayout
fragmentTransaction.replace(R.id.example_contentpane,
newFragment);
fragmentTransaction.commit();
//this is set so the onBackPressed() method knows how to operate.
tabContentIndex =0;
}
public void startTestFragment(){
Fragment testFragment = new TestFragment(this);
FragmentManager fragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.replace(R.id.example_contentpane,
testFragment);
fragmentTransaction.commit();
//different contentIndex
tabContentIndex = 1;
}
//this method called by the Activity
@Override
public void onBackPressed() {
//this will close the app because we are at the top of the hierarchy
if(tabContentIndex==0){
((MainActivity)getActivity()).close();
//this will switch to the original content fragment.
}else if(tabContentIndex==1||tabContentIndex==2){
startExampleFragment();
}
}
}
FragmentTransaction有一个方法addToBackStack()。
以这种方式打开新碎片this:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
那不是一个好的导航方法。我建议你看看Android设计模式并重新思考你的流程。
但是,如果不编写自己的FragmentManager
,你需要拥有多个FragmentActivities
。
考虑使用TaskStacks,但这只适用于HoneyComb。因此,我建议重新考虑你的导航或仅构建一个HC+应用程序。
我知道我没有给你太多代码来解决你的问题。但是请好好阅读Android Navigation,它解释了时间和祖先导航,这是从Android 3.0+开始“官方”添加的。
现在,jetpack-navigation-component
已经内置支持此功能。
从版本开始
navigation-2.4.0-alpha01
fragment-1.4.0-alpha01
感谢Ian。这里有他的一篇很棒的解释。
或者,如果你不想使用Navigation Component,你可以使用FragmentManager
中可用的savebackStack()
和restoreBackStack()
方法。这些方法也在上面的链接中描述了。为此,您需要使用fragment-1.4.0-alpha01
依赖项或最新版本。