简体   繁体   中英

Why in different themes different buttons are created?

I have an usual button and a theme which is applied to android:theme in AndroidManifest file:

<Button
    android:id="@+id/supperButton"
    android:layout_width="match_parent"
    android:layout_height="120dp" />
<style name="AppTheme" parent="Theme.AppCompat">
</style>

When i inflate this button and stop the app with debugger to see what class has been created i see the following: 在此处输入图像描述

As you can see, instead of an usual button class, AppComapatButton has been created. When i change theme to as follows:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
</style>

MaterialButton is created, instead of an usual button class or AppComapatButton :

在此处输入图像描述

Question: as i can gather, themes can define what exactly type of a widget is used. So what exactly does define it? Maybe there is some attribute in a theme that does it?

It happens if your Activity extends AppCompatActivity .

The AppCompatActivity calls the setFactory2 method using a custom implementation of LayoutInflater.
This implementation is done by the AppCompatViewInflater which checks the names of the views in the layout and automatically "substitutes" all usages of core Android widgets inflated from layout files by the AppCompat extensions of those widgets.

You can check in the source code:

@Nullable
public final View createView(/**...*/) {
    //...
    switch (name) {
        case "Button":
            view = createButton(context, attrs);
            verifyNotNull(view, name);
            break;
     //...
}

@NonNull
protected AppCompatButton createButton(Context context, AttributeSet attrs) {
    return new AppCompatButton(context, attrs);
}

In the MaterialComponents theme is defined another implemetantion, the MaterialComponentsViewInflater .

For example you can check in the source code:

@Override
  protected AppCompatButton createButton(@NonNull Context context, @NonNull AttributeSet attrs) {
    return new MaterialButton(context, attrs);
  }

You can use an own inflater adding in the app theme the viewInflaterClass attribute:

  <style name="Theme.App" parent="Theme.MaterialComponents.*">
    <item name="viewInflaterClass">com.google.android.material.theme.MaterialComponentsViewInflater</item>
  </style>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM