如何在 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
包?或者这些依赖关系在哪些文件中确定?
TextView、Buttons 等都是默认捆绑的,但其他小部件如 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对于许多平台 View
s,所以你至少应该知道这一点。
AndroidX 的 Factory
将 View
创建委托给助手 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
,这些标签通常会被 LayoutInflater
或 Factory
使用。由于您是自己处理这些布局,因此您可能需要确定这些布局对您的特定目标意味着什么。
<include>
, reusing complete layouts.
<merge>
, reusing layout "inners", without an enclosing parent.
<requestFocus>
,试图在布局后设置焦点。
<tag>
,用于在布局 XML 中向 View
添加键控标签(仅限 Lollipop 及更高版本)。
<blink>
,一个你可能永远不会看到的 Easter egg。
<fragment>
,实际上由 Activity
作为其 LayoutInflater
的私有 Factory2
. 处理
最后,还有 <view>
标签 – 小写 v
– 它必须有一个 class
属性(无前缀),其值指定所需的 View
class,缩写或全称。这种替代格式的存在是为了允许嵌套 classes,因为它们的名称将包含 $
字符,这在 XML 标记名称中是不允许的。
出于某种原因,我想获取布局文件中使用的小部件的完整 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
包?或者这些依赖关系在哪些文件中确定?
TextView、Buttons 等都是默认捆绑的,但其他小部件如 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对于许多平台 View
s,所以你至少应该知道这一点。
AndroidX 的 Factory
将 View
创建委托给助手 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
,这些标签通常会被 LayoutInflater
或 Factory
使用。由于您是自己处理这些布局,因此您可能需要确定这些布局对您的特定目标意味着什么。
<include>
, reusing complete layouts.<merge>
, reusing layout "inners", without an enclosing parent.<requestFocus>
,试图在布局后设置焦点。<tag>
,用于在布局 XML 中向View
添加键控标签(仅限 Lollipop 及更高版本)。<blink>
,一个你可能永远不会看到的 Easter egg。<fragment>
,实际上由Activity
作为其LayoutInflater
的私有Factory2
. 处理
最后,还有 <view>
标签 – 小写 v
– 它必须有一个 class
属性(无前缀),其值指定所需的 View
class,缩写或全称。这种替代格式的存在是为了允许嵌套 classes,因为它们的名称将包含 $
字符,这在 XML 标记名称中是不允许的。