【问题标题】:Programmatically add Fragment to an Activity in Kotlin以编程方式将 Fragment 添加到 Kotlin 中的 Activity
【发布时间】:2020-05-09 13:57:56
【问题描述】:

我已经构建了一个片段,我希望将其放置在一个活动上。

到目前为止,我的代码如下所示:

MainActivity.kt

class MainActivity: AppCompatActivity() {

    @Inject
    lateinit var teamInfoModule: TeamInfoModule;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        DaggerServiceModuleComponent.create().inject(this)

        val bundle = Bundle()
        val teamArrayList: ArrayList<Team> = this.teamInfoModule.getAllTeamData()
        val homeFragment = HomeFragment()

        bundle.putParcelableArrayList("teamData", teamArrayList)
        homeFragment.arguments = bundle

        val fragmentManager: FragmentManager = supportFragmentManager
        val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
        fragmentTransaction.replace(R.id.home_fragment, homeFragment).commit()
    }
}

activity_main.xml

<layout 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:id="@+id/activity_main">
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

HomeFragment.kt

class HomeFragment @Inject constructor(): Fragment() {

    lateinit var team: Team

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        super.onCreateView(inflater, container, savedInstanceState)

        DaggerServiceModuleComponent.create().inject(this)

        val binding: ViewDataBinding = DataBindingUtil.inflate<ViewDataBinding>(inflater, R.layout.layout_home, container, false)
        print(arguments.toString())
        val allTeams: ArrayList<Team> = arguments?.get("teamData") as ArrayList<Team>

        this.team = allTeams[0]

        binding.setVariable(BR.team, team)

        return binding.root
    }
}

layout_home.xml(绑定到 HomeFragment)

<?xml version="1.0" encoding="utf-8"?>

<layout 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">

    <data>
        <variable
            name="team"
            type="com.example.bluelightlite.models.Team" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".fragments.HomeFragment">

        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="1dp"
            android:layout_marginTop="79dp"
            android:layout_marginEnd="1dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:id="@+id/info_text"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="@{team.name}"/>
        </androidx.cardview.widget.CardView>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

当它运行时,我得到错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.bluelightlite, PID: 10421
    java.lang.IllegalArgumentException: No view found for id 0x7f07003a (com.example.bluelightlite:id/activity_main) for fragment HomeFragment{4b02ab3 (55c458bd-2931-48c6-8087-5e82641313c1) id=0x7f07003a}

【问题讨论】:

    标签: android xml android-fragments kotlin


    【解决方案1】:

    将片段添加到 Activity

    private fun addFragmentToActivity(fragment: Fragment?){
    
        if (fragment == null) return
        val fm = supportFragmentManager
        val tr = fm.beginTransaction()
        tr.add(R.id.framlayout, fragment)
        tr.commitAllowingStateLoss()
        curFragment = fragment
    }
    

    在片段中添加片段

    private fun addFragmentToFragment(fragment: Fragment){
    
     val ft = childFragmentManager.beginTransaction()
        ft.add(R.id.framlayout, fragment, fragment.javaClass.name)
        ft.commitAllowingStateLoss()
    }
    

    【讨论】:

    • 尽量不要保留curFragment,除非您还通过当前已知的活动findFragmentByTagonCreate 中初始化它。
    【解决方案2】:

    异常表示您正在尝试添加要与不存在的视图关联的片段。其实我也不确定R.id.home_fragment是从哪里来的。

    解决办法是这样的:

    <FrameLayout
        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=".MainActivity"
        android:id="@+id/root_container">
    </FrameLayout>
    

    然后

    if(savedInstanceState == null) { // initial transaction should be wrapped like this
        supportFragmentManager.beginTransaction()
               .replace(R.id.root_container, homeFragment)
               .commitAllowingStateLoss()
    }
    

    所以说使用containerR.id.container 的另一个答案也是正确的,但是您也缺少setContentView(R.layout.activity_main)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    

    【讨论】:

    • 完美!!!非常感谢,我认为这里每个人的回答都是正确的,但没有人提到 setContentView... 设置为接受的答案
    • 可以用androidx.fragment.app.FragmentContainerView代替FrameLayout吗?
    • 当然,如果你愿意
    【解决方案3】:

    用这样的容器 id 替换这一行

    fragmentTransaction.replace(R.id.container, homeFragment).commit()
    

    并在您的 mainactivity xml 中添加框架布局

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

    【讨论】:

    • 嘿,我已经按照你说的做了,但现在我得到了同样的错误```No view found for id 0x7f070049 (com.example.bluelightlite:id/container) for fragment HomeFragment{4b02ab3 (6dc9e25c-d62f-4ef7-a264-2ef39a773b5a) id=0x7f070049} ```
    【解决方案4】:

    你需要给你的片段一个 id 并在活动布局中引用它。例如:

    
    <fragment   android:name=com.example.bluelightlite.models.Team"
                android:id="@+id/Team"
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="match_parent" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      • 1970-01-01
      • 2020-11-22
      • 2021-11-12
      相关资源
      最近更新 更多