如何在 Android 布局 xml 文件中获取小部件的完整 class 名称?

How to get the full class name of a widget in the Android layout xml file?

出于某种原因,我想获取布局文件中使用的小部件的完整 class 名称。有些以完整的 class 名称显示,例如 android.support.constraint.ConstraintLayout,而有些默认小部件则不是。

例如下面的代码中,TextView其实对应的是android.widget.TextView.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />

XML 文件中所有这些带有缩写形式的小部件类型标签都来自 android.widget 包?或者这些依赖关系在哪些文件中确定?

TextViewButtons 等都是默认捆绑的,但其他小部件如 Constraint Layout 等它们默认情况下不捆绑它们是支持库的一部分。这就是为什么您需要提供完整的包名。另一方面,您也可以对默认捆绑的小部件执行相同的操作(您也可以在 XML 中为文本视图提供完整的包名称)。但是没有必要这样做。

首先让我说,仅通过检查布局,您无法真正确定标记将产生的确切运行时类型。 LayoutInflater 是处理将布局转换为运行时 View 层次结构的(基础)class,它的 Factory 接口“插件”设置,以及 Android 的开放继承组件设计,提出几个可以修改或完全覆盖默认布局 inflation 的点。此外,没有技术要求任何特定名称产生 View.

的任何特定子类型

但是,一般来说,您可以安全地做出一些基本假设 – 例如,<Button> 标签可能会导致 android.widget.Button 的实例,或者子 class 其中 - 因为否则事情可能会很快变得荒谬和崩溃。大多数情况下,这些 inflation 修改是为了增强或扩展基础 UI 类型,而不是疯狂地改变标准程序。

也就是说,平台 inflater 将按顺序在以下四个包中查找任何不包含句点 (.) 的 View 名称,这是用于区分缩写 class 名称和完全限定名称的唯一标准:

  • android.widget,其中可以找到大多数可用平台 View classes。
  • android.webkit,对于 <WebView>
  • android.app,对于 <ActivityView>,仅供系统使用,对 SDK 隐藏。
  • android.view<View><SurfaceView><TextureView>,还有一些隐藏的。

不过,在此之前,它将首先有机会创建一个 View 到(可能)多个 Factory 实现,并且它不会费心去查看这些 return 一个。如果他们不这样做,那么 inflater 将检查上述包,依次将每个包添加到缩写名称之前,并尝试使用 Context 将结果加载为 View subclass的 ClassLoader.

如果缩写名称不存在于任何这些包中,您最终会得到一个重新抛出的 ClassNotFoundException(包装在 InflateException 中),并带有一条消息 Didn't find class "android.view.BadLayoutTagName",显示 android.view 确实是最后检查的包裹。


这些天最常见的外部 Factory 实现可能来自 AndroidX 和 Material 组件库,它们都将替换它们自己的扩展 classes对于许多平台 Views,所以你至少应该知道这一点。

AndroidX 的 FactoryView 创建委托给助手 class、AppCompatViewInflater,这会进行以下替换:

Tag name: In package androidx.appcompat.widget:
AutoCompleteTextView AppCompatAutoCompleteTextView
Button AppCompatButton
CheckBox AppCompatCheckBox
CheckedTextView AppCompatCheckedTextView
EditText AppCompatEditText
ImageButton AppCompatImageButton
ImageView AppCompatImageView
MultiAutoCompleteTextView AppCompatMultiAutoCompleteTextView
RadioButton AppCompatRadioButton
RatingBar AppCompatRatingBar
SeekBar AppCompatSeekBar
Spinner AppCompatSpinner
TextView AppCompatTextView
ToggleButton AppCompatToggleButton

Material 组件库建立在 AndroidX 之上,它进一步定制了 AppCompatViewInflater 与它自己的子 class、MaterialComponentsViewInflater,覆盖了因此,上面的几个替换:

Tag name: In package com.google.android.material:
AutoCompleteTextView textfield.MaterialAutoCompleteTextView
Button button.MaterialButton
CheckBox checkbox.MaterialCheckBox
RadioButton radiobutton.MaterialRadioButton
TextView textview.MaterialTextView

最后,我要提到的是还有其他各种标签不适用于 View,这些标签通常会被 LayoutInflaterFactory 使用。由于您是自己处理这些布局,因此您可能需要确定这些布局对您的特定目标意味着什么。

最后,还有 <view> 标签 – 小写 v – 它必须有一个 class 属性(无前缀),其值指定所需的 View class,缩写或全称。这种替代格式的存在是为了允许嵌套 classes,因为它们的名称将包含 $ 字符,这在 XML 标记名称中是不允许的。