片段内部片段

我需要你帮忙研究碎片内部,实际上我 我面对一个问题按下后退按钮。应用程序主屏幕 有按钮,并按下每个按钮视图替换为新的 片段(该片段包含在另一个片段中) , 动态添加/替换片段工作正常,通过按 按钮1片段更换,同样的情况下按下按钮,但如果 我再次按下按钮,得到了一个例外:

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

意味着片段或内部片段已经添加,我正在尝试 再加上它们,任何人都知道如何处理里面的碎片 碎片和来回移动没有任何问题,感谢 支持。

MainActivity,其中动态地添加片段和 被取代了。

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);
}
}
}

这里是 Layout: main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">


<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">


<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />


<Button
android:id="@+id/button2"
android:text="Button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />


<Button
android:id="@+id/button3"
android:text="Button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />


<Button
android:id="@+id/button4"
android:text="Button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>


<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>

希望我已经尽力解决我的问题了。

284848 次浏览

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


更新

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

目前还没有对 MapFragment的支持,Android 团队说他们从 Android 3.0开始就一直在研究这个问题。关于这个问题的更多信息,但是您可以通过创建返回 MapActivity的片段来完成。给你是一个代码示例。多亏了伊纳扎鲁克:

工作原理:

  • MainFragmentActivity 是扩展 FragmentActivity并承载两个 MapFragments 的活动。
  • MyMapActivity 扩展了 MapActivity 并具有 MapView.
  • LocalActivityManagerFragment托管 LocalActivityManager。
  • MyMapFragment 扩展了 LocalActivityManagerFragment,并在 TabHost的帮助下创建了 MyMapActivity 的内部实例。

如果你有任何疑问,请告诉我

片段可以添加到其他片段中,但是每次调用父片段的 onDestroyView()方法时,都需要从父片段中删除片段。然后再次将其添加到 Parent 片段的 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();
}

您可以将 FrameLayout添加到片段中,并在它初始化时将其替换为另一个片段。

这样,您可以将另一个片段视为位于第一个片段内部。

嗨,我解决了这个问题,把每个片段到不同的布局。我只是相关的布局可见,并使其他可见性消失。

我的意思是:

<?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>

我假设您将打开您的网页按钮1被点击。您可以通过单击操作控制片段的可见性。你可以让相关的布局可见,其他的都消失了,通过片段管理器你可以获取你的片段。这个方法对我很有效。从 有可见性的视图: gone 是不可见的,它不占用任何空间用于布局目的,我认为这种方法不会造成任何空间问题。开始

PS: 我只是试图解释我的解决方案代码可能有语法错误或结构不完整。

自从 Android 4.2(API 17)嵌套片段变成可用的 http://developer.android.com/about/versions/android-4.2.html#NestedFragments以来

要将片段放在其他片段中,可以使用 getChildFragmentManager ()

它也可在支持库!

我解决了这个问题。可以使用 Support 库和 ViewPager。如果你不需要手势滑动,你可以禁用滑动。因此,这里有一些代码来改进我的解决方案:

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;
}
}

附注: 这是一个丑陋的测试代码,但它提高了测试的可能性。

P.P.S. 内部片段 ABC0应传递给 ViewPagerAdapter

当前在嵌套片段中,只有通过编程方式生成的嵌套片段才受到支持!因此此时在 xml 布局方案中不支持嵌套的片段布局!

使用 getChildFragmentManager () ,点击链接: 嵌套碎片

你可以使用 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) {




}




}

enter image description here

我需要更多的上下文,所以我做了一个例子来说明如何做到这一点。我在准备期间读到的最有用的东西是这样的:

活动

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");
}
}

父片段

片段 _ father. 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);
}
}

儿童碎片

片段 _ 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之前使用。

这没什么复杂的。我们不能在这里使用 getFragmentManager()。对于使用片段 在一个碎片里,我们使用 getChildFragmentManager()。其余部分都是一样的。

这可以帮助那些在 科特林上工作的人可以使用扩展函数 创建一个 kotlin 文件,比如说 “ util.kt”然后添加这段代码

fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {


val transaction = childFragmentManager.beginTransaction()
transaction.replace(frameId, fragment).commit()
}

假设这是 孩子的类

class InputFieldPresentation: Fragment()
{
var views: View? = null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
views = inflater!!.inflate(R.layout.input_field_frag, container, false)
return views
}


override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
}
...
}

现在您可以像这样将子元素添加到 父亲的碎片

 FatherPresentation:Fragment()
{
...


override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val fieldFragment= InputFieldPresentation()
addChildFragment(fieldFragment,R.id.fragmet_field)
}
...
}

其中 R.id.fragmet _ field是包含片段的布局的 id。当然,这个漏洞就在父亲的碎片里面。 这里有一个例子

Father _ Fragment.xml :

<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>


...


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/fragmet_field"
android:orientation="vertical"
>
</LinearLayout>
...


</LinearLayout>