在 FragmentManager 中更改片段

Posted

技术标签:

【中文标题】在 FragmentManager 中更改片段【英文标题】:Issue changing fragment in FragmentManager 【发布时间】:2016-04-04 08:50:24 【问题描述】:

New Layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_
    android:layout_ >
    
    <FrameLayout
        android:layout_
        android:layout_
        android:layout_above="@+id/L1" >
        
        <fragment
            android:id="@+id/fragment_place"
            android:name="com.javacodegeeks.android.fragmentstest.HomeFrag"
            android:layout_
            android:layout_ />
        
   </FrameLayout>     

    <RelativeLayout
        android:id="@+id/L1"
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true" >
        
     
       <ImageView
            android:id="@+id/button1"
            android:layout_
            android:layout_
            android:src="@drawable/home"
            android:onClick="selectFrag"
            android:layout_alignParentLeft="true"/>
        
         <ImageView
            android:id="@+id/button2"
            android:layout_
            android:layout_
            android:src="@drawable/search"
            android:onClick="selectFrag"
            android:layout_toRightOf="@+id/button1"/>
         
           <ImageView
            android:id="@+id/button3"
            android:layout_
            android:layout_
            android:src="@drawable/map"
            android:onClick="selectFrag"
            android:layout_toRightOf="@+id/button2"/>
         
         
    
    
    </RelativeLayout>

</RelativeLayout>

我正在学习使用 FragmentManager 在 ImageView 单击上更改片段。当我单击第一个 imageView 时,带有文本“home”的主要片段布局显示良好。但是当点击其他ImageViews改变fragment页面时,它会更改为新的fragment页面,但不会删除之前的页面。结果,上一页与新页混在一起。 It look like this. 截图显示主页,文本为“home”,即上一页,新页面,文本为“search”。点击新的ImageView时如何删除上一页?

MainActivity

public class MainActivity extends Activity 
	
	private static final int RESULT_SETTINGS = 1;


	@Override
	protected void onCreate(Bundle savedInstanceState) 
      super.onCreate(savedInstanceState);

      setContentView(R.layout.demo);
      
    
      
	
	
	
	 
	public void selectFrag(View view) 
		 Fragment fr = null;
		 
		 if(view == findViewById(R.id.button1)) 
			 fr = new HomeFrag();
		 
		 else if(view == findViewById(R.id.button2))
			 fr = new SearchFrag();
		 
		 else if(view == findViewById(R.id.button3))
			 fr = new MapFrag();
		 
		 
		 
		 FragmentManager fm = getFragmentManager();
	     FragmentTransaction fragmentTransaction = fm.beginTransaction();
	     fragmentTransaction.replace(R.id.fragment_place, fr);
	     fragmentTransaction.commit();
		 
	
	
	
	
	
	
	
	
	
   

【问题讨论】:

在框架布局中使用片段阅读此answer 【参考方案1】:

作为Android guide on starting fragments says 当您希望片段更改时,您不要在布局文件中使用fragment 元素。你应该使用一些布局,例如FrameLayout

如果您计划在活动的生命周期内更改片段,这是必要的。

我认为这是导致您的问题的原因。


您的新 XML 布局很接近,但我的意思是完全不使用 &lt;fragment&gt;

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_place"
    android:layout_
    android:layout_>

</FrameLayout>  

然后代码本身还有更多工作要做,因为您需要在首次创建 UI 时创建/附加“home”片段。

在你的public void onCreate(Bundle savedInstanceState)

添加它以创建/附加第一个“home”片段。

 if (findViewById(R.id.fragment_place) != null) 

        // However, if we're being restored from a previous state,
        // then we don't need to do anything and should return or else
        // we could end up with overlapping fragments.
        if (savedInstanceState != null) 
            return;
        

        // Create a new Fragment to be placed in the activity layout
        HomeFrag firstFragment = new HomeFrag();

        // In case this activity was started with special instructions from an
        // Intent, pass the Intent's extras to the fragment as arguments
        //   firstFragment.setArguments(getIntent().getExtras());
        // I commented this out since you don't appear to need it right now.

        // Add the fragment to the 'fragment_container' FrameLayout
        getFragmentManager().beginTransaction()
                .add(R.id.fragment_container, firstFragment).commit();
    

【讨论】:

***.com/a/17495250/2801237 这里很好地解释了为什么你应该使用 framelayout。 我添加了 FrameLayout 并在其中插入了片段,但问题仍然存在。我在帖子中编辑了布局代码。 @mawalker 非常感谢。它工作得很好。 @mawalker。【参考方案2】:

用框架布局包装。试试这个xml

说明here

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_
android:layout_ >
<Framelayout
  android:layout_
  android:layout_>
    <fragment
        android:id="@+id/fragment_place"
        android:name="com.javacodegeeks.android.fragmentstest.HomeFrag"
        android:layout_
        android:layout_
        android:layout_above="@+id/L1" />
  </framelayout>
<RelativeLayout
    android:id="@+id/L1"
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true" >


   <ImageView
        android:id="@+id/button1"
        android:layout_
        android:layout_
        android:src="@drawable/home"
        android:onClick="selectFrag"
        android:layout_alignParentLeft="true"/>

     <ImageView
        android:id="@+id/button2"
        android:layout_
        android:layout_
        android:src="@drawable/search"
        android:onClick="selectFrag"
        android:layout_toRightOf="@+id/button1"/>

       <ImageView
        android:id="@+id/button3"
        android:layout_
        android:layout_
        android:src="@drawable/map"
        android:onClick="selectFrag"
        android:layout_toRightOf="@+id/button2"/>




</RelativeLayout>

【讨论】:

我将根布局更改为框架布局,但仍然不好。 @Zeeshan【参考方案3】:

试试这个代码 sn-p 会起作用

        FragmentManager fm = getFragmentManager();
        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        Fragment currentFragment =   getSupportFragmentManager().findFragmentById(R.id.fragment_place);
        if(currentFragment!=null)
            fragmentTransaction.remove()
        else
            fragmentTransaction.add(R.id.fragment_place, fr);
            `enter code here`
            fragmentTransaction.commit();
        

【讨论】:

以上是关于在 FragmentManager 中更改片段的主要内容,如果未能解决你的问题,请参考以下文章

FragmentManager popBackStack 不删除片段

Android - 通过 FragmentManager 替换片段后,片段返回到它们的第一个状态

在 FragmentManager 中管理 BackStackEntries

使用 (Child)FragmentManager 正确使用子子片段

片段声明的目标片段不属于此 FragmentManager - Android

如何避免 FragmentManager 重新创建片段?