【问题标题】:Cannot uniquely identify layout when adding nested fragments with fragmenttransaction使用片段事务添加嵌套片段时无法唯一标识布局
【发布时间】:2017-12-28 00:20:46
【问题描述】:

我正在尝试执行以下操作:

  1. 在活动中,替换容器为片段 (TestFragment)
  2. 此片段的布局包含一个容器,该容器被另一个片段 (TestSubFragment)替换
  3. 单击 TestSubFragment 会使活动在根容器上添加一个新的 TestFragment

TestActivity.kt

class TestActivity : AppCompatActivity(), TestSubFragment.OnFragmentInteractionListener {

override fun onFragmentInteraction(id: Int) {
    supportFragmentManager.beginTransaction().add(R.id.container, TestFragment.newInstance(id)).addToBackStack(null).commit()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_test)
    supportFragmentManager.beginTransaction().replace(R.id.container, TestFragment.newInstance(1)).addToBackStack(null).commit()
}
}

TestFragment.kt

class TestFragment : Fragment() {

private var id: Int? = null

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val v = inflater!!.inflate(R.layout.fragment_test, container, false)
    activity.supportFragmentManager.beginTransaction().replace(R.id.sub_fragment_container, TestSubFragment.newInstance(id!!)).commit()
    return v
}
companion object {
    fun newInstance(id: Int): TestFragment {
        val fragment = TestFragment()
        fragment.id = id
        return fragment
    }
}
}

TestSubFragment.kt

class TestSubFragment : Fragment() {

private var mListener: OnFragmentInteractionListener? = null
private var id: Int? = null

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val v = inflater!!.inflate(R.layout.fragment_sub_test, container, false)
    v.id_text.text = id.toString()
    v.id_text.setOnClickListener { _ -> mListener?.onFragmentInteraction(v.id_text.text.toString().toInt() + 1) }
    return v
}

override fun onAttach(context: Context?) {
    super.onAttach(context)
    if (context is OnFragmentInteractionListener) {
        mListener = context
    }
}

interface OnFragmentInteractionListener {
    fun onFragmentInteraction(id: Int)
}

companion object {
    fun newInstance(id: Int): TestSubFragment {
        val fragment = TestSubFragment()
        fragment.id = id
        return fragment
    }
}
}

activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="ckl.happens.TestActivity">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>

</android.support.constraint.ConstraintLayout>

fragment_test.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    tools:context="ckl.happens.TestFragment">

    <FrameLayout
        android:id="@+id/sub_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>
</FrameLayout>

fragment_sub_test.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    tools:context="ckl.happens.TestFragment">

    <TextView
        android:id="@+id/id_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

问题是 TestFragment.kt 中的替换片段行正在从 xml 层次结构中找到第一个 R.id.sub_fragment_container,因此它正在替换不正确的容器而不是最后一个/新容器。

我尝试在 fragmenttransaction 中添加标签或将 R.id.sub_fragment_container 更改为 v.sub_fragment_container.id 但没有运气。

我不想在 onFragmentInteraction 中将 add() 更改为 replace(),因为片段将被重新创建,并且我希望在用户返回该片段时保持片段中的所有内容不变。

我找不到关于我的案例嵌套片段的详细文章。

我正在使用 Kotlin,但我也能理解 Java。谢谢!

【问题讨论】:

    标签: java android android-fragments kotlin


    【解决方案1】:

    我在没有获得新容器 ID 的情况下解决了我的问题。

    我决定删除 fragmenttransaction 并在 xml 中添加片段。然后在包含子fragment的fragment(父fragment)中,得到childFragmentManager.findFragmentById(R.id.fragment)的子fragment。最后从父片段更新子片段的内容。

    class TestActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_test)
    
            val fragment1 = TestFragment.newInstance(1)
            supportFragmentManager.beginTransaction().replace(R.id.container, fragment1).commit()
    
            val fragment2 = TestFragment.newInstance(2)
            supportFragmentManager.beginTransaction().add(R.id.container, fragment2).addToBackStack(null).commit()
    
            val fragment3 = TestFragment.newInstance(3)
            supportFragmentManager.beginTransaction().add(R.id.container, fragment3).addToBackStack(null).commit()
        }
    }
    
    class TestFragment : Fragment() {
        private var id: Int? = null
    
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val v = inflater!!.inflate(R.layout.fragment_test, container, false)
            val subFragment = childFragmentManager.findFragmentById(R.id.fragment) as TestSubFragment
            subFragment.view?.findViewById<TextView>(R.id.id_text)?.text = id.toString()
            return v
        }
    
        companion object {
            fun newInstance(id: Int): TestFragment {
                val fragment = TestFragment()
                fragment.id = id
                return fragment
            }
        }
    }
    
    class TestSubFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater!!.inflate(R.layout.fragment_sub_test, container, false)
        }
    }
    

    activity_test.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="ckl.happens.TestActivity">
    
        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">
        </FrameLayout>
    
    </android.support.constraint.ConstraintLayout>
    

    fragment_test.xml

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        tools:context="ckl.happens.TestFragment">
    
        <fragment
            android:id="@+id/fragment"
            android:name="ckl.happens.TestSubFragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </FrameLayout>
    

    fragment_sub_test.xml

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        tools:context="ckl.happens.TestFragment">
    
        <TextView
            android:id="@+id/id_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="" />
    
    </FrameLayout>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多