在 Kotlin 中的片段内加载片段
Load fragments inside fragment in Kotlin
我心中有一个应用程序结构:
仪表板Activity
- 主页片段
- AdsFragment
- 问候片段
- 经验片段
考虑到这一点,我尝试在 HomeFragment
中加载不同的片段,这也是一个片段
我在HomeFragment的onCreateView()
中写了如下代码
val fm : FragmentManager = childFragmentManager
val container = R.id.greetingFragmentContainer
val greetingFragment : Fragment? = fm.findFragmentById(R.id.fragmentGreeting)
if (greetingFragment != null) {
fm.beginTransaction().replace(container, greetingFragment).commit()
} else {
Log.e("HomeFragment", "Fragment not found")
}
fragment_greeting.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/fragmentGreeting"
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="._fragments.dash.GreetingFragment">
<ImageView
android:id="@+id/profile_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:src="@drawable/loading"/>
</FrameLayout>
使用该 if 语句,我发现 greetingFragment
值返回 null。
我做错了什么?
主页片段应包含三个框架布局,用于加载 AdsFragment、Greetings Fragment、Experience Fragment。
可以使用子片段管理器将片段加载到框架布局。
在你的 HomeFragment
中试试这个
lateinit var context: AppCompatActivity
override fun onAttach(context: Context) {
super.onAttach(context)
this.context = context as AppCompatActivity
}
并调用没有 findFragmentbyId
的片段,如下所示:
val fm = context.supportFragmentManager
val fragmentTransaction: FragmentTransaction
val fragment = GreetingFragment()
fragmentTransaction = fm.beginTransaction()
fragmentTransaction.replace(R.id.container, fragment)
.addToBackStack(null)
fragmentTransaction.commit()
有多种方法可以实例化片段。您使用的方法除了声明布局外什么都不做,这不是您想要的!使用以下方法正确执行。
<LinearLayout>
<fragment android:id="@+id/ad" android:name="._fragments.dash.AdFragment" />
<fragment android:id="@+id/greeting" android:name="._fragments.dash.GreetingFragment"/>
<fragment android:id="@+id/experience" android:name="._fragments.dash.ExpFragment"/>
</LinearLayout>
此处,android:name中指定的classes指的是扩展片段class的专用片段classes。您需要在专用布局资源中指定每个片段的布局,例如R.layout.ad_fragment、R.layout.greeting_fragment 和 R.layout.exp_fragment,必须在每个 Class.
的 onCreateView() 函数中进行扩充
为了在同一视图中加载不同的片段,我这样做了。
private val manager = supportFragmentManager
当你必须加载每个片段时(不要认为你必须同时显示所有片段)你可以这样做
val transaction = manager.beginTransaction()
val fragment = FragmentOne()
transaction.replace(R.id.fragment_holder, fragment)
transaction.addToBackStack(null)
transaction.commit()
当声明监听不同的按钮 tapu 然后实例化不同的片段时,最好有一个通用的做法,因为制作不同的按钮会创建更多的复制代码。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val fragment = when(item.itemId) {
R.id.ads_menu -> FragmentAds()
R.id.grets_menu -> FragmentGreeting()
R.id.exp_menu -> FragmentExperience()
else -> return super.onOptionsItemSelected(item)
}
val transaction= manager.beginTransaction()
transaction.replace(R.id.fragment_holder, fragment)
transaction.addToBackStack(null)
transaction.commit()
return true
}
当然有三个片段 class 有自己的布局并覆盖所有方法。
我也在探查器中尝试过这个,似乎是这样。
关于这个解决方案的问题(如果我们可以这样调用)是在按下后加载所有片段的历史记录,因为替换删除并添加一个新片段。
为了避免这种情况,所有片段都可以是可见的,并且更改按钮只是更改所选的片段,当然这会使 when 语句变得复杂。
ft = fm.beginTransaction();
ft.hide(getFragmentManager().findFragmentByTag("searchFragment"));
ft.add(R.id.main_fragment, yourDetailfragment);
ft.addToBackStack(null);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
我心中有一个应用程序结构:
仪表板Activity
- 主页片段
- AdsFragment
- 问候片段
- 经验片段
考虑到这一点,我尝试在 HomeFragment
中加载不同的片段,这也是一个片段
我在HomeFragment的onCreateView()
val fm : FragmentManager = childFragmentManager
val container = R.id.greetingFragmentContainer
val greetingFragment : Fragment? = fm.findFragmentById(R.id.fragmentGreeting)
if (greetingFragment != null) {
fm.beginTransaction().replace(container, greetingFragment).commit()
} else {
Log.e("HomeFragment", "Fragment not found")
}
fragment_greeting.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/fragmentGreeting"
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="._fragments.dash.GreetingFragment">
<ImageView
android:id="@+id/profile_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:src="@drawable/loading"/>
</FrameLayout>
使用该 if 语句,我发现 greetingFragment
值返回 null。
我做错了什么?
主页片段应包含三个框架布局,用于加载 AdsFragment、Greetings Fragment、Experience Fragment。 可以使用子片段管理器将片段加载到框架布局。
在你的 HomeFragment
lateinit var context: AppCompatActivity
override fun onAttach(context: Context) {
super.onAttach(context)
this.context = context as AppCompatActivity
}
并调用没有 findFragmentbyId
的片段,如下所示:
val fm = context.supportFragmentManager
val fragmentTransaction: FragmentTransaction
val fragment = GreetingFragment()
fragmentTransaction = fm.beginTransaction()
fragmentTransaction.replace(R.id.container, fragment)
.addToBackStack(null)
fragmentTransaction.commit()
有多种方法可以实例化片段。您使用的方法除了声明布局外什么都不做,这不是您想要的!使用以下方法正确执行。
<LinearLayout>
<fragment android:id="@+id/ad" android:name="._fragments.dash.AdFragment" />
<fragment android:id="@+id/greeting" android:name="._fragments.dash.GreetingFragment"/>
<fragment android:id="@+id/experience" android:name="._fragments.dash.ExpFragment"/>
</LinearLayout>
此处,android:name中指定的classes指的是扩展片段class的专用片段classes。您需要在专用布局资源中指定每个片段的布局,例如R.layout.ad_fragment、R.layout.greeting_fragment 和 R.layout.exp_fragment,必须在每个 Class.
的 onCreateView() 函数中进行扩充为了在同一视图中加载不同的片段,我这样做了。
private val manager = supportFragmentManager
当你必须加载每个片段时(不要认为你必须同时显示所有片段)你可以这样做
val transaction = manager.beginTransaction()
val fragment = FragmentOne()
transaction.replace(R.id.fragment_holder, fragment)
transaction.addToBackStack(null)
transaction.commit()
当声明监听不同的按钮 tapu 然后实例化不同的片段时,最好有一个通用的做法,因为制作不同的按钮会创建更多的复制代码。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val fragment = when(item.itemId) {
R.id.ads_menu -> FragmentAds()
R.id.grets_menu -> FragmentGreeting()
R.id.exp_menu -> FragmentExperience()
else -> return super.onOptionsItemSelected(item)
}
val transaction= manager.beginTransaction()
transaction.replace(R.id.fragment_holder, fragment)
transaction.addToBackStack(null)
transaction.commit()
return true
}
当然有三个片段 class 有自己的布局并覆盖所有方法。 我也在探查器中尝试过这个,似乎是这样。
关于这个解决方案的问题(如果我们可以这样调用)是在按下后加载所有片段的历史记录,因为替换删除并添加一个新片段。
为了避免这种情况,所有片段都可以是可见的,并且更改按钮只是更改所选的片段,当然这会使 when 语句变得复杂。
ft = fm.beginTransaction();
ft.hide(getFragmentManager().findFragmentByTag("searchFragment"));
ft.add(R.id.main_fragment, yourDetailfragment);
ft.addToBackStack(null);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();