【问题标题】:Load fragments inside fragment in Kotlin在 Kotlin 中的片段内加载片段
【发布时间】:2019-11-29 09:33:00
【问题描述】:

我有一个应用程序结构:

仪表板活动

  • 首页片段
    • 广告片段
    • 问候片段
    • 体验片段

考虑到这一点,我正在尝试在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。

我做错了什么?

【问题讨论】:

  • 尝试 android:name 在 中指定片段类
  • @RahulShukla 没用。对不起:/
  • 对不起,我也错过了。
  • 老实说,您不只是在寻找 ViewPager + FragmentPagerAdapter 吗?
  • 哦,我把那个组合记下来了。只是,我想要一些片段是静态的并且以编程方式加载的地方。

标签: android android-fragments kotlin fragment


【解决方案1】:

有多种方法可以实例化片段。您使用的方法除了声明一个布局之外什么都不做,这不是您想要的!使用以下方法正确完成。

<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 中指定的类是指扩展 Fragment 类的专用 Fragment 类。您需要在专用布局资源中指定每个片段的布局,例如R.layout.ad_fragment、R.layout.greeting_fragment 和 R.layout.exp_fragment,必须在每个 Class 的 onCreateView() 函数中进行膨胀。

更多信息请参考Official Android documentation

【讨论】:

  • 这是静态的,但它有助于我的情况。谢谢。
【解决方案2】:

在你的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()

【讨论】:

  • 不需要那个lateinit var,片段已经有一个getActivity()方法。
  • @EpicPandaForce 是的,我们可以使用该方法,但我有时会遇到崩溃,所以这是我认为的安全方法。
【解决方案3】:

首页片段应包含三个框架布局,用于加载 AdsFragment、Greetings Fragment、Experience Fragment。 可以使用子片段管理器将片段加载到框架布局。

【讨论】:

    【解决方案4】:

    为了在同一个视图中加载不同的片段,我这样做了。

        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
    }
    

    当然,有三个片段类有它们的布局并覆盖所有方法。 我也在探查器中尝试过这个,似乎是这样。

    关于这个解决方案的问题(如果我们可以这样调用的话)是在按下后加载所有片段的历史记录,因为替换删除并添加一个新的。

    为了避免这种情况,所有片段都可以可见,更改按钮只需更改选定的按钮,但当然它会使 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();
    

    【讨论】:

      猜你喜欢
      • 2019-03-07
      • 1970-01-01
      • 2022-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 2020-04-18
      相关资源
      最近更新 更多