Reputation: 413
For some reason, I want to get the full class name of a widget used in the layout file. Some are displayed by full class name like android.support.constraint.ConstraintLayout
while some default widgets are not.
For example, in the code below, TextView
actually corresponds to android.widget.TextView
.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
All these widget type tags with abbreviated form in XML files come from android.widget
package? Or in which files these dependencies determined?
Upvotes: 3
Views: 2017
Reputation: 39191
Let me begin by saying that you can't really be certain of the exact runtime type that a tag will result in merely by inspecting the layout. LayoutInflater
is the (base) class that handles translating layouts to runtime View
hierarchies, and its Factory
interface "plugin" setup, along with Android's open inheritance component design, present several points where default layout inflation can be modified, or completely overridden. Furthermore, there is no technical requirement that any particular name produce any specific subtype of View
.
However, you're probably safe to make some basic assumptions, in general – e.g., a <Button>
tag will likely result in an instance of android.widget.Button
, or a subclass thereof – because otherwise things could get nonsensical and broken pretty quick. Most often, these inflation modifications are made in order to enhance or extend the base UI types, rather than to wildly alter the standard procedures.
That said, on its own the platform inflater will look in the following four packages, in order, for any View
name that does not contain a period (.
), which is the sole criterion used to distinguish abbreviated class names from fully qualified ones:
android.widget
, where most of the available platform View
classes are to be found.android.webkit
, for <WebView>
.android.app
, for <ActivityView>
, used only by the system and hidden from the SDK.android.view
, for <View>
, <SurfaceView>
, <TextureView>
, and a few more hidden ones.Before that, though, it will have given first chance to create a View
to (potentially) multiple Factory
implementations, and it will not bother to look if any of those return one. If they don't, then the inflater will check the aforementioned packages, successively prepending each one to the abbreviated name, and attempting to load the result as a View
subclass using the Context
's ClassLoader
.
If the abbreviated name doesn't exist in any of those packages, you will eventually get a rethrown ClassNotFoundException
(wrapped in an InflateException
) with a message saying Didn't find class "android.view.BadLayoutTagName"
, showing that android.view
is indeed the last package checked.
Possibly the most common external Factory
implementation these days comes from the AndroidX and Material Components libraries, and those both will substitute their own extended classes for a number of the platform View
s, so you should at least be aware of this.
AndroidX's Factory
delegates View
creation to a helper class, AppCompatViewInflater
, which makes the following substitutions:
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 |
The Material Components library is built on AndroidX, and it further customizes AppCompatViewInflater
with its own subclass, MaterialComponentsViewInflater
, overriding a few of the above substitutions thusly:
Tag name: | In package com.google.android.material : |
---|---|
AutoCompleteTextView |
textfield.MaterialAutoCompleteTextView |
Button |
button.MaterialButton |
CheckBox |
checkbox.MaterialCheckBox |
RadioButton |
radiobutton.MaterialRadioButton |
TextView |
textview.MaterialTextView |
Lastly, I would mention that there are various other tags that are not for View
s, and that would normally be consumed by LayoutInflater
or a Factory
. Since you're processing these layouts yourself, you may need to decide what these mean for your specific aims.
<include>
, for reusing complete layouts.<merge>
, for reusing layout "inners", without an enclosing parent.<requestFocus>
, for attempting to set the focus after layout.<tag>
, for adding keyed tags to View
s in layout XML (only on Lollipop and later versions).<blink>
, an Easter egg that you likely won't ever see.<fragment>
, actually handled by the Activity
as its LayoutInflater
's private Factory2
.Finally, there is the <view>
tag – with a lowercase v
– which must have a class
attribute (no prefix) with a value specifying the desired View
class, abbreviated or full. This alternate format exists to allow for nested classes, as their names will contain the $
character, which is not allowed in an XML tag name.
Upvotes: 3
Reputation: 4678
TextView, Buttons etc are all these bundled by default but other widgets like Constraint Layout and etc they are not bundled by default they are part of support library. That's why you need give full package name. On the other hand, you can do the Same thing with widgets those are bundled by default as well(you can give complete package name for text view as well in XML). But there is no need to do so.
Upvotes: 1