即使在高 API 级别设备上,Androidx AppCompatButton 看起来也与 Button 不同

Lud*_*g W 10 android android-button material-design material-components-android androidx

根据文档

支持旧版本平台上兼容功能的按钮,包括:

允许通过 ViewCompat 中的背景色调方法对其背景进行动态色调。允许使用 R.attr.backgroundTint 和 R.attr.backgroundTintMode 设置背景色调。当您在布局中使用 Button 并且顶级活动/对话框由 appcompat 提供时,这将自动使用。您应该只需要在编写自定义视图时手动使用此类。

现在,这让我假设以下两个按钮在高级设备上看起来完全相同。

<androidx.appcompat.widget.AppCompatButton
        android:text="AppCompatButton"
        android:id="@+id/appcompatbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

<Button
        android:layout_below="@id/appcompatbutton"
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:text="Button"
        android:layout_height="wrap_content" />
Run Code Online (Sandbox Code Playgroud)

然而,这是它的实际外观:

在此处输入图片说明

我在以下模拟器上运行了这个:Galaxy Nexus,API:28 (720 x 1280 xhdpi)

当我像这样在 appTheme 中应用 buttonStyle 时:

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="buttonStyle">@style/Widget.MaterialComponents.Button</item>
</style>
Run Code Online (Sandbox Code Playgroud)

它改变了 AppCompatButton 而不是像这样的普通按钮:(注意圆角边缘的细微差别)

在此处输入图片说明

我还尝试创建一个既继承自 android.widget.Button 又继承自 androidx.appcompat.widget.AppCompatButton 的自定义按钮,这两个按钮显示的行为与在 xml 中使用 AppCompatButton 的行为相同。所以感觉唯一的异常值是 XML 中的 Button。

问题 1:

在我看来,这一切似乎令人难以置信。有人可以将此澄清为错误或功能吗?

编辑 1

做调试我发现按钮实际上变成了一个MaterialButton,看下面: 在此处输入图片说明

问题2:

为什么会发生这种转变?

编辑 2

问题 2 答案:

Button 到 MaterialButton 的转换是由于我使用的父主题。

问题 3:

你如何实现一个自定义按钮,就像 xml 中的 Button 一样?

作为旁注和个人意见,也是一个轻微的重复,这个系统不仅令人困惑,而且很难做到正确,并且对于未来的变化来说是万无一失的。除此之外,文档很差。如果也包含对此的答案,或者至少讨论一下,例如如何处理它,我将不胜感激。

Gab*_*tti 4

简短的答案。

在我看来,这一切似乎令人难以置信。有人可以将此澄清为错误还是功能吗?

他们使用不同的风格。

为什么会发生这种转变?

启用了自动膨胀,它将在运行时替换<Button<com.google.android.material.button.MaterialButton

如何实现一个自定义按钮,其工作方式就像 xml 中的 Button 一样?

您可以自定义 xml 中的属性或主题属性。

很长的答案。

  1. 他们使用不同的风格。

默认样式MaterialButtonWidget.MaterialComponents.Button. 此样式继承Widget.AppCompat.Button但更改了一些属性。 在这里您可以找到差异。

主要区别在这里

<item name="shapeAppearance">?attr/shapeAppearanceSmallComponent</item>
Run Code Online (Sandbox Code Playgroud)

您可以在官方文档中阅读有关塑造的更多信息。如果您浏览样式,您会发现:

  <style name="ShapeAppearance.MaterialComponents.SmallComponent">
    <item name="cornerSize">@dimen/mtrl_shape_corner_size_small_component</item>
  </style>
Run Code Online (Sandbox Code Playgroud)

其中mtrl_shape_corner_size_small_component= 4dp。它解释了圆边的细微差别。

另外你正在使用 <item name="buttonStyle">@style/Widget.MaterialComponents.Button</item>.

它不适用于 MaterialButton。你必须使用:

<item name="materialButtonStyle">@style/Widget.MaterialComponents.Button</item>
Run Code Online (Sandbox Code Playgroud)
  1. 自动通货膨胀在这里

MaterialComponentsViewInflater如果正在使用材质组件主题,则在膨胀时会用材质组件替换一些框架小部件。
AppCompat 也会发生类似的情况(您可以检查一下MaterialComponentsViewInflater extends AppCompatViewInflater)。

这意味着,如果您使用的是 Material 主题,则<Button会在运行时被替换。<com.google.android.material.button.MaterialButton

  1. 有不同的选择。其中之一是为按钮定义自定义样式。
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
    ...
    <item name="materialButtonStyle">@style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
   <item name="cornerRadius">xxx</item>
</style>
Run Code Online (Sandbox Code Playgroud)

或者

  <style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
    <item name="shapeAppearanceOverlay">@style/SShapeAppearanceOverlay.MyApp.Button.Rounded</item>
  </style>

  <style name="ShapeAppearanceOverlay.MyApp.Button.Rounded" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">xxdp</item>
  </style>
Run Code Online (Sandbox Code Playgroud)