Programmatically add Fragment to an Activity in Kotlin
Solution 1
The exception says you are trying to add the Fragment to be associated with a view that doesn't exist. In fact, I'm not sure where R.id.home_fragment
comes from.
Solution is this:
<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>
Then
if(savedInstanceState == null) { // initial transaction should be wrapped like this
supportFragmentManager.beginTransaction()
.replace(R.id.root_container, homeFragment)
.commitAllowingStateLoss()
}
So the other answer was also correct that said to use container
and R.id.container
, but you are also missing setContentView(R.layout.activity_main)
.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Solution 2
Add fragment to 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
}
Add Fragment in Fragment
private fun addFragmentToFragment(fragment: Fragment){
val ft = childFragmentManager.beginTransaction()
ft.add(R.id.framlayout, fragment, fragment.javaClass.name)
ft.commitAllowingStateLoss()
}
Solution 3
replace this line with container id like this
fragmentTransaction.replace(R.id.container, homeFragment).commit()
and add framelayout in your mainactivity xml
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
/>
Solution 4
You need to give your fragment an id and reference it in the activity layout. E.g:
<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" />
Marc Freeman
Updated on May 15, 2020Comments
-
Marc Freeman about 4 years
I have built a fragment that I wish to place on an activity.
So far, my code looks like this:
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 (tied to 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>
When it runs, I get the error:
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}
-
Marc Freeman over 4 yearsHey, I've done as you've said but now I'm getting the same error ``` No view found for id 0x7f070049 (com.example.bluelightlite:id/container) for fragment HomeFragment{4b02ab3 (6dc9e25c-d62f-4ef7-a264-2ef39a773b5a) id=0x7f070049} ```
-
EpicPandaForce over 4 yearsTry not to keep a
curFragment
unless you also initialize it inonCreate
via the currently known activefindFragmentByTag
. -
Marc Freeman over 4 yearsPERFECT!!! thank you so much, I think everyone's answer was correct here but no one mentioned the setContentView... Set as accepted answer
-
AdiAtAnd over 3 yearsCan use androidx.fragment.app.FragmentContainerView right instead of FrameLayout?
-
EpicPandaForce over 3 yearsSure, if you want