如何从 Android 库中创建和显示片段?

How to create and display Fragments from inside an Android Library?

我对 Android / Kotlin 比较陌生。

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

显示来自 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)
            }
        }
    }
}

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

I wonder how Android libraries like AdMob manage to create and show a View (especially an Intersitial Ad) from inside a library without any layout preparation of the integrating app.

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

I assume this View is some sort of Fragment.

你为什么会这么认为?它可能是一个片段,但它会包含在一个 Activity 中,它可以按照我在上面指出的那样启动。

This Guide states, that to add a fragment programmatically, "the layout should include a FragmentContainerView". Additionally in the sample code from the same guide the id of said FragmentContainerView is used to add the fragment. This id is not known inside the library.

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

我成功了。

可在此处找到工作演示: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
    }
}

在我的 activity 中:

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 导致了异常并使应用程序崩溃。