【问题标题】:How to create and display Fragments from inside an Android Library?如何从 Android 库中创建和显示片段?
【发布时间】:2021-05-22 14:57:07
【问题描述】:

我对 Android / Kotlin 比较陌生。

我想知道像 AdMob 这样的 Android 库是如何在没有任何集成应用布局准备的情况下从库内部创建和显示视图(尤其是插页式广告)的。我认为这个视图是某种片段。

显示来自AdMob 的插页式广告的示例代码:

我认为这与在 show 方法中作为参数传递的 Activity 有关。

if (mInterstitialAd != null) {
  mInterstitialAd?.show(this)
} else {
  Log.d("TAG", "The interstitial ad wasn't ready yet.")
}

Guide 声明,要以编程方式添加片段,“布局应包含 FragmentContainerView”。此外,在同一指南的示例代码中,所述 FragmentContainerView 的 id 用于添加片段。这个 id 在库中是未知的。

class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                add<ExampleFragment>(R.id.fragment_container_view)
            }
        }
    }
}

这样的库是如何做到这一点的?

【问题讨论】:

    标签: android kotlin fragment


    【解决方案1】:

    我想知道像 AdMob 这样的 Android 库如何在没有任何集成应用布局准备的情况下从库中创建和显示视图(尤其是插页式广告)。

    集成应用需要做哪些“布局准备”?给定一个您传递给该方法的 Activity,任何代码都可以使用 Activity.startActivity 来启动它自己的 Activity,该 Activity 可以通过库选择的任何布局以任何方式设置样式/主题(例如显示插页式广告)。

    我认为这个视图是某种片段。

    你为什么会这样假设?它可以是一个 Fragment,但它会包含在一个 Activity 中,可以像我上面指出的那样启动它。

    本指南指出,要以编程方式添加片段,“布局应包含 FragmentContainerView”。此外,在同一指南的示例代码中,所述 FragmentContainerView 的 id 用于添加片段。这个 id 在库中是未知的。

    没错。但这再次假设图书馆只使用片段并试图将其推入您的层次结构。这是极不可能的。它更有可能开始一个它知道并可以完全控制的全新 Activity。

    【讨论】:

    • 感谢您的回复!我认为所有活动都必须在 mainfest 中声明,这是我想避免的。是否必须声明这样的活动?
    • 确实如此 - 库会在自己的清单中声明它,然后它会合并到您的清单中。您可以查看清单的最终输出并确认是这种情况:developer.android.com/studio/build/…
    【解决方案2】:

    我设法做到了。

    可以在此处找到工作演示:https://github.com/eat-your-broccoli/add-fragment-from-library-demo

    图书馆:

    class FragmentManager {
        companion object {
            fun showFragment(activity: AppCompatActivity) {
    (activity.supportFragmentManager.findFragmentById(android.R.id.content) == null) {
                    activity.supportFragmentManager.beginTransaction()
                        .add(android.R.id.content, DemoFragment())
                        .addToBackStack(null)
                        .commit()
                }
            }
        }
    }
    
    class DemoFragment : Fragment() {
    
        private lateinit var btnBack: Button
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            var view = inflater.inflate(R.layout.fragment_demo, container, false)
    
            // enable back button
            btnBack = view.findViewById(R.id.btn_back)
            btnBack.setOnClickListener {
                this.activity?.supportFragmentManager?.popBackStack()
            }
            return view
        }
    }
    

    在我的活动中:

    class MainActivity : AppCompatActivity() {
        lateinit var btnSwitch: Button
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            btnSwitch = findViewById(R.id.btn_switch)
            btnSwitch.setOnClickListener {
                FragmentManager.showFragment(this)
            }
        }
    }
    

    我遇到的一个问题是使用R.id.content 而不是android.R.id.content 导致执行并导致应用程序崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 2021-12-04
      • 2015-01-29
      • 1970-01-01
      相关资源
      最近更新 更多