MaterialButton 的宽度、高度问题

2022-07-09  本文已影响0人  小强开学前

最近写一个自定义控件,发现 MaterialButton 相关的问题颇多,在此记录

1. MaterialButton 文字与 Icon 的BUG

结果按钮与文字之间有一定距离,后来在GitHub上发现这是一个BUG,升级版本修复

结果 Icon跑到文字前边,后来发现只能设置 IconGravity 为 end

2. 如何让 MaterialButton 的大小变小,或者说看起来像TextView

结合使用minWidth/minHeight,minimalWidth/minimalHeight,insetTop/...,leftPadding/...

3. OutlinedButton 宽度问题

设置三个View,分别为 MaterialButton、TextView、View
统一设置背景、文字颜色、文字大小,比较各长度
View 是通过测量出数字然后设置宽度

文字 打印
My Application 295,292, 292
My ApplicationApplication 519,514, 514

另外一台手机居然三个数字都不同

发现跟背景、圆角都没关系,代码里设置 background 为 null 也不行
跟上面第二点的最小宽度也没关系
甚至 IconSize 和 IconPadding 我也尝试了,没有关系

然后看显示效果,发现 Button 的文字粗一些,难道跟 fontWeight 有关系?

显示效果

确实是,修改 TypeFace 之后宽度一样了

继续研究,发现
MaterialButton 默认的是TypeFace@20046,style为0,weight为500
MaterialTextView 默认的是TypeFace@20087,style为0,weight为400

TextView使用的是默认字体,这个每个手机都可以自己设置,我这里是TypefaceCompat.create(it.context, Typeface.SANS_SERIF, Typeface.NORMAL)

而 MaterialButton 是 style 为Widget.MaterialComponents.Button下的<item name="android:textAppearance">?attr/textAppearanceButton</item>指定的

继续找,发现textAppearance是在style为Widget.Material.Button下的<item name="textAppearance">?attr/textAppearanceButton</item>指定的。

也就是说,取决于我们项目中使用的主题里面的这个属性
而我的测试Demo是Theme.MaterialComponents.DayNight.DarkActionBar,继续看一下。

Base.V14.Theme.MaterialComponents.Light.Bridge => <item name="textAppearanceButton">@style/TextAppearance.MaterialComponents.Button</item>

最终找到

<style name="TextAppearance.MaterialComponents.Button" parent="Base.TextAppearance.MaterialComponents.Button">
<!-- Roboto Medium was added in this api level -->
<item name="fontFamily">sans-serif-medium</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>

结论:

Button、TextView等即使去除所有影响布局的因素仍然可能大小不同,本质是字体不同,MaterialButton 默认使用 FontWeight 为500的字体,而 FontWeight 在API28才被添加。

TextPaint 也有个 TypeFace,所以很可能出现三个不一样的值。

测试代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/btn"
        style="@style/Widget.MaterialComponents.Button.OutlinedButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:letterSpacing="0"
        android:minWidth="0dp"
        android:minHeight="0dp"
        android:padding="0dp"
        android:text="@string/app_name"
        android:textAllCaps="false"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="16dp"
        app:backgroundTint="@color/black"
        app:cornerRadius="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:strokeWidth="0dp" />

    <TextView
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dp"
        android:background="@color/black"
        android:text="@string/app_name"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn" />

    <View
        android:id="@+id/test"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_marginTop="2dp"
        android:background="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn2" />

</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {

    private lateinit var mBinding: ActivityMainBinding

    private var itemCount = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mBinding.root)


        val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
        paint.textSize = 16.dp

        mBinding.test.doOnPreDraw {
            val w = paint.measureText(it.context.getString(R.string.app_name)).toInt()
            it.layoutParams.width = w
            Log.d("lq","${mBinding.btn.measuredWidth},${mBinding.btn2.measuredWidth}, $w")
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读