以编程方式将 Fragment 添加到 Kotlin 中的 Activity
Posted
技术标签:
【中文标题】以编程方式将 Fragment 添加到 Kotlin 中的 Activity【英文标题】:Programmatically add Fragment to an Activity in Kotlin 【发布时间】: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_
android:layout_
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_
android:layout_
tools:context=".fragments.HomeFragment">
<androidx.cardview.widget.CardView
android:layout_
android:layout_
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_
android:layout_
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 HomeFragment4b02ab3 (55c458bd-2931-48c6-8087-5e82641313c1) id=0x7f07003a
【问题讨论】:
【参考方案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
,除非您还通过当前已知的活动findFragmentByTag
在onCreate
中初始化它。【参考方案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_
android:layout_
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()
所以说使用container
和R.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_
android:layout_
android:id="@+id/container"
/>
【讨论】:
嘿,我已经按照你说的做了,但现在我得到了同样的错误```No view found for id 0x7f070049 (com.example.bluelightlite:id/container) for fragment HomeFragment4b02ab3 (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_
android:layout_ />
【讨论】:
以上是关于以编程方式将 Fragment 添加到 Kotlin 中的 Activity的主要内容,如果未能解决你的问题,请参考以下文章
如何接收 GPS 位置并膨胀 Fragment MapView 以使用 SyncAdapter 以编程方式添加标记
以编程方式将 UISearchBar 添加到普通 ViewController 中以编程方式添加的 UITableView