在片段里面的片段

我需要关于片段内碎片的帮助,实际上我在按下button时遇到问题。 应用程序主屏幕上有button,按下每个button视图replace为新的片段(该片段包含在另一个片段内),dynamic添加/replace片段工作正常,按下button1片段replace,同样按下button时,但如果我按button再次,得到一个exception:

"Duplicate id 0x7f05000a, tag null, or parent id 0x7f050009 with another fragment for com........ fragmentname" 

意思是已经添加了片段或内部片段,我试图再次添加它们,任何人都知道如何使用片段内部的片段并且没有任何问题来回移动,感谢支持。

MainActivity,其中片段是dynamic添加和replace的。

  public class FragmentInsideFragmentTestActivity extends Activity { private Button button1; private Button button2; private Button button3; private Button button4; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); button1 =(Button) this.findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button2 =(Button) this.findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button3 =(Button) this.findViewById(R.id.button3); button3.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button4 =(Button) this.findViewById(R.id.button4); button4.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); } public void onButtonClick(View v) { Fragment fg; switch (v.getId()) { case R.id.button1: fg=FirstFragment.newInstance(); replaceFragment(fg); break; case R.id.button2: fg=SecondFragment.newInstance(); replaceFragment(fg); break; case R.id.button3: fg=FirstFragment.newInstance(); replaceFragment(fg); break; case R.id.button4: fg=SecondFragment.newInstance(); replaceFragment(fg); break; } } private void replaceFragment(Fragment newFragment) { FragmentTransaction trasection = getFragmentManager().beginTransaction(); if(!newFragment.isAdded()){ try{ //FragmentTransaction trasection = getFragmentManager().beginTransaction(); trasection.replace(R.id.linearLayout2, newFragment); trasection.addToBackStack(null); trasection.commit(); }catch (Exception e) { // TODO: handle exception //AppConstants.printLog(e.getMessage()); } }else trasection.show(newFragment); } } 

这里是布局:main.xml

  <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:id="@+id/button1" android:layout_height="wrap_content" android:text="Button1"></Button> <Button android:text="Button2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"></LinearLayout> </LinearLayout> 

希望我试图清除我的问题。

AFAIK,片段不能容纳其他片段。


UPDATE

使用当前版本的Android支持包(或API级别17以上的本机片段),可以通过getChildFragmentManager()嵌套片段。 请注意,这意味着您需要在API级别11-16上使用Android支持包版本的片段,因为即使这些设备上存在片段的本机版本,该版本也没有getChildFragmentManager()

由于Android 4.2(API 17)嵌套片段变得可用http://developer.android.com/about/versions/android-4.2.html#NestedFragments

要将片段放置在其他片段中,请使用getChildFragmentManager()

它也支持库中可用!

在这里输入图像描述

我需要更多的背景,所以我举了一个例子来说明如何完成这个过程。 我在准备时阅读的最有帮助的是这样的:

  • 创build和使用片段

活动

activity_main.xml中

添加一个FrameLayout到你的活动来保存父代片段。

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Activity"/> <FrameLayout android:id="@+id/parent_fragment_container" android:layout_width="match_parent" android:layout_height="200dp"/> </LinearLayout> 

MainActivity.java

加载父代片段并实现片段监听器。 (见片段沟通 。)

 import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Begin the transaction FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.parent_fragment_container, new ParentFragment()); ft.commit(); } @Override public void messageFromParentFragment(Uri uri) { Log.i("TAG", "received communication from parent fragment"); } @Override public void messageFromChildFragment(Uri uri) { Log.i("TAG", "received communication from child fragment"); } } 

家长片段

fragment_parent.xml

为子片段添加另一个FrameLayout容器。

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:background="#91d0c2"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Parent fragment"/> <FrameLayout android:id="@+id/child_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </LinearLayout> 

ParentFragment.java

onViewCreated使用getChildFragmentManager来设置子片段。

 import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; public class ParentFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_parent, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { Fragment childFragment = new ChildFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.replace(R.id.child_fragment_container, childFragment).commit(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromParentFragment(Uri uri); } } 

儿童片段

fragment_child.xml

这里没什么特别的。

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:background="#f1ff91"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Child fragment"/> </LinearLayout> 

ChildFragment.java

这里也没什么特别的。

 import android.support.v4.app.Fragment; public class ChildFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_child, container, false); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromChildFragment(Uri uri); } } 

笔记

  • 正在使用支持库,以便在Android 4.2之前可以使用嵌套的片段 。

片段可以添加到其他片段中,但是每次调用父片段的onDestroyView()方法时,都需要将其从父代片段中移除。 再次将它添加到Parent Fragment的OnCreateView()方法中。

只是这样做:

 @Override public void onDestroyView() { FragmentManager mFragmentMgr= getFragmentManager(); FragmentTransaction mTransaction = mFragmentMgr.beginTransaction(); Fragment childFragment =mFragmentMgr.findFragmentByTag("qa_fragment") mTransaction.remove(childFragment); mTransaction.commit(); super.onDestroyView(); } 

我解决了这个问题。 您可以使用支持库和ViewPager 。 如果您不需要通过手势轻扫,则可以禁用滑动。 所以这里有一些代码来改进我的解决scheme:

 public class TestFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag, container, false); final ArrayList<Fragment> list = new ArrayList<Fragment>(); list.add(new TrFrag()); list.add(new TrFrag()); list.add(new TrFrag()); ViewPager pager = (ViewPager) v.findViewById(R.id.pager); pager.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) { @Override public Fragment getItem(int i) { return list.get(i); } @Override public int getCount() { return list.size(); } }); return v; } } 

PS是testing的丑陋的代码,但它可能改善。

PPS 里面片段ChildFragmentManager应该传递给ViewPagerAdapter

您可以将FrameLayout添加到片段,并在初始化时将其replace为其他片段。

这样,你可以考虑把另一个片段放在第一个片段中。

你可以使用getChildFragmentManager()函数。

例:

父代片段:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.parent_fragment, container, false); } //child fragment FragmentManager childFragMan = getChildFragmentManager(); FragmentTransaction childFragTrans = childFragMan.beginTransaction(); ChildFragment fragB = new ChildFragment (); childFragTrans.add(R.id.FRAGMENT_PLACEHOLDER, fragB); childFragTrans.addToBackStack("B"); childFragTrans.commit(); return rootView; } 

父级布局( parent_fragment.xml ):

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <FrameLayout android:id="@+id/FRAGMENT_PLACEHOLDER" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> 

儿童片段:

 public class ChildFragment extends Fragment implements View.OnClickListener{ View v ; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub View rootView = inflater.inflate(R.layout.child_fragment, container, false); v = rootView; return rootView; } @Override public void onClick(View view) { } } 

使用getChildFragmentManager(),按照链接: 嵌套片段

没有支持MapFragment,Android团队说自从Android 3.0开始工作。 这里有关于http://code.google.com/p/android/issues/detail?id=15347&utm_source=buffer&buffer_share=acc72这个问题的更多信息,但是你可以通过创build一个返回MapActivity的Fragment来实现。; 这是一个代码示例。 感谢inazaruk: https : //github.com/inazaruk/examples/tree/master/MapFragmentExample

怎么运行的:

-MainFragmentActivity是扩展FragmentActivity并承载两个MapFragments的活动。 -MyMapActivity扩展了MapActivity并具有MapView。 – LocalActivityManagerFragment承载LocalActivityManager。 -MyMapFragment扩展LocalActivityManagerFragment,并在TabHost的帮助下创buildMyMapActivity的内部实例。 如果您有任何疑问,请告诉我

在嵌套的片段中,只有通过编程生成才支持嵌套的片段! 所以在这个时候xml布局scheme中不支持嵌套的片段布局!

它没什么复杂的。 我们不能在这里使用getFragmentManager()。 为了在片段中使用片段,我们使用getChildFragmentManager()。 rest将是一样的。

您好我解决了这个问题,把每个片段放在不同的布局。我做了相关的布局可见,使其他人的可见性消失。

我的意思是:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:id="@+id/button1" android:layout_height="wrap_content" android:text="Button1"></Button> <Button android:text="Button2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> <LinearLayout android:layout_width="full_screen" android:layout_height="0dp" android:layout_weight="1" android:id="action_For_Button1" android:visibility="visible"> <Fragment android:layout_width="full_screen" android:layout_height="full_screen" android:id="fragment1" . . . / > </LinearLayout> <LinearLayout android:layout_width="full_screen" android:layout_height="0dp" android:id="action_For_Button1" android:layout_weight="1" android:visibility="gone"> <Fragment android:layout_width="full_screen" android:layout_height="full_screen" android:id="fragment2" . . . / > </LinearLayout> . . . </LinearLayout> 

我认为你会打开你的页面,因为button1被点击。你可以控制你的片段的可见性点击action.You可以使相关的布局可见,其他人走了,通过片段pipe理器,你可以把你的片段。这种方法为我工作。而且,由于可见性:消失的观点是不可见的,并且不需要任何空间来进行布局,所以我认为这种方法不会造成任何空间问题。

PS:我只是试图解释我的解决scheme代码可能有语法错误或未完成的结构。