在Android中膨胀类按钮时出错

Posted

技术标签:

【中文标题】在Android中膨胀类按钮时出错【英文标题】:Error inflating class Button in Android 【发布时间】:2016-03-23 17:25:15 【问题描述】:

我有一个最小 sdk 16 到 23 的应用程序。我想尽可能地使用 Material Design。它还必须是全屏应用程序。包括 AppCompat 支持库。现在我有一些按钮的登录活动:

<Button
    android:id="@+id/act_logon_btn_logon"
    style="@style/ButtonDefault"
    android:layout_
    android:layout_
    android:text="@string/act_logon_logon" />

样式如下(values/styles.xml):

<style name="Theme.AppCompat.Light.NoActionBar.FullScreen" parent="@style/Theme.AppCompat.Light">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar.FullScreen"></style>

<style name="AppTheme" parent="AppThemeBase"></style>

<style name="ButtonDefault" parent="Widget.AppCompat.Button">
    <item name="android:textSize">?attr/font_medium</item>
</style>

<style name="FontStyle"></style>

<style name="FontStyle.Small">
    <item name="font_small">12sp</item>
    <item name="font_medium">14sp</item>
    <item name="font_large">16sp</item>
</style>

<style name="FontStyle.Medium">
    <item name="font_small">16sp</item>
    <item name="font_medium">18sp</item>
    <item name="font_large">20sp</item>
</style>

<style name="FontStyle.Large">
    <item name="font_small">20sp</item>
    <item name="font_medium">22sp</item>
    <item name="font_large">24sp</item>
</style>

在值/属性中:

<declare-styleable name="FontStyle">
    <attr name="font_small" format="dimension" />
    <attr name="font_medium" format="dimension" />
    <attr name="font_large" format="dimension" />
</declare-styleable>

属性font_medium 定义如here 所述。我不明白的行为是,当登录活动被打开时,一切正常,没有例外。但是,当我从带有片段的登录活动中打开另一个活动并且片段有一个具有这种样式的按钮时,我得到一个异常,说“错误膨胀类按钮”。当我从 ButtonDefault 样式中删除 textSize 属性时,一切正常。为什么它在某处有效而在某处无效?自定义属性有问题吗?

我尝试使用该样式创建 values-v21/styles.xml,但没有效果。

您能否解释一下以下父样式定义之间的区别?我要迷路了。

parent="Widget.AppCompat.Button"
parent="@style/Widget.AppCompat.Button"
parent="android:Widget.Button"
parent="android:Widget.AppCompat.Button"
parent="android:Widget.Material.Button"
parent="android:style/Widget.Material.Button"

谢谢。

编辑 1 - 例外:

12-17 10:56:53.950: E/AndroidRuntime(7251): FATAL EXCEPTION: main
12-17 10:56:53.950: E/AndroidRuntime(7251): Process: test.android, PID: 7251
12-17 10:56:53.950: E/AndroidRuntime(7251): java.lang.RuntimeException: Unable to start activity ComponentInfotest.dci.android/test.dci.android.view.activity.TransactionActivity: android.view.InflateException: Binary XML file line #49: Error inflating class Button
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2702)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread.access$900(ActivityThread.java:177)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.os.Handler.dispatchMessage(Handler.java:102)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.os.Looper.loop(Looper.java:145)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread.main(ActivityThread.java:5951)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at java.lang.reflect.Method.invoke(Native Method)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at java.lang.reflect.Method.invoke(Method.java:372)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
12-17 10:56:53.950: E/AndroidRuntime(7251): Caused by: android.view.InflateException: Binary XML file line #49: Error inflating class Button
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at test.dci.android.view.fragment.TransactionFragment.onCreateView(TransactionFragment.java:71)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1226)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1328)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2284)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at test.dci.android.view.activity.TransactionActivity.onCreateView(TransactionActivity.java:1)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:740)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at test.dci.android.view.activity.TransactionActivity.onCreate(TransactionActivity.java:31)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.Activity.performCreate(Activity.java:6289)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655)
12-17 10:56:53.950: E/AndroidRuntime(7251):     ... 10 more
12-17 10:56:53.950: E/AndroidRuntime(7251): Caused by: java.lang.RuntimeException: Failed to resolve attribute at index 12
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:582)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.widget.TextView.<init>(TextView.java:1400)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.widget.Button.<init>(Button.java:115)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.widget.Button.<init>(Button.java:108)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.widget.AppCompatButton.<init>(AppCompatButton.java:62)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.widget.AppCompatButton.<init>(AppCompatButton.java:58)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:98)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:938)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:992)
12-17 10:56:53.950: E/AndroidRuntime(7251):     at 

【问题讨论】:

你能把你的错误贴出来 完成。错误不仅发生在按钮上,而且发生在 edittexts 上 - 样式包含自定义 fontSize 属性 似乎android.view.InflateException: Binary XML file line #49: Error inflating class Button 异常是由java.lang.RuntimeException: Failed to resolve attribute at index 12 引起的,似乎充气机在识别?attr/font_medium 时遇到问题。您是否尝试将其更改为一个值,即:14sp,而不是删除 textSize? 如果我将 textSize 更改为特定值,如您所说,它可以工作。 【参考方案1】:

将图像文件从“drawable-v24”文件夹复制到“drawable”文件夹。问题解决了。信用:https://github.com/chrisjenx/Calligraphy/issues/417

【讨论】:

这是我的问题。【参考方案2】:

我通过为 21 以下的 api 创建自己的 appcompat 样式来修复它,

styles.xml

  <style name="ColoredButtonAppcompat">
    <item name="android:textAppearance">@style/ButtonTextStyle</item>
    <item name="android:background">@drawable/colored_button_background</item>
    <item name="android:minHeight">48dip</item>
    <item name="android:minWidth">88dip</item>
    <item name="android:focusable">true</item>
    <item name="android:clickable">true</item>
    <item name="android:gravity">center_vertical|center_horizontal</item>
</style>

<style name="ButtonTextStyle" >
    <item name="android:textSize">14dp</item>
    <item name="android:textColor">@android:color/white</item>
</style>

styles-v21.xml

&lt;style name="ColoredButtonAppcompat" parent="Widget.AppCompat.Button.Colored"/&gt;

【讨论】:

【参考方案3】:

解决了。问题是充气机的属性是未知的(或未指定)。解决方案是在膨胀使用该属性的视图之前定义属性值。

解决方案1: 具有该属性的样式不仅必须在activity中指定,而且在具有该属性的一些视图的fragment中也必须指定。所以将此行添加到片段的onCreateView() 之前 膨胀片段的根视图的行:

getContext().getTheme().applyStyle(fontStyleResId, true);

解决方案2:直接在应用主题中设置属性值:

<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar.FullScreen">
    <item name="font_small">@dimen/font_size_medium_small</item>
    <item name="font_medium">@dimen/font_size_medium_medium</item>
    <item name="font_large">@dimen/font_size_medium_large</item>
</style>

【讨论】:

【参考方案4】:

正如我们在评论部分所讨论的,问题在于充气机不知何故无法识别?attr/font_medium,从而引发了异常。

您可以使用 dimens.xml 文件指定自定义尺寸,如下所示:

<resources> 
    <dimen name="small">14sp</dimen>
    <dimen name="medium">16sp</dimen>
    <dimen name="large">18sp</dimen>
</resources>

然后在你的styles.xml中你像这样引用这些值:

<style name="ButtonDefault" parent="Widget.AppCompat.Button">
    <item name="android:textSize">@dimen/medium</item>
</style>

与其他所有资源一样,dimens.xml 可以放置在相应的资源文件夹中,以适应特定的设备配置(屏幕尺寸、密度、语言等)。

【讨论】:

我对Android开发有点生疏了,但是我认为你在使用 但在这种情况下,我无法在应用程序中使用不同的字体大小作为用户在偏好活动中的选择......或者如何组合它? 您不能以编程方式设置样式。您可以允许用户选择首选字体并从dimens.xml 文件中获取相应的尺寸(记住dimens.xml 是一个资源文件)。之后,您将字体大小设置为小部件。 我不能?到目前为止,我使用的是 getTheme().applyStyle() 方法并且它有效......我怎样才能以编程方式做到这一点?我唯一想要的就是能够在偏好活动中选择字体大小,仅此而已。【参考方案5】:

我在使用 Kotlin 进行开发时遇到了类似的情况: 为了解决这个问题,将app中drawable-24中的内容复制到drawable中。 这样做是为了支持较旧的 Android 设备。

【讨论】:

以上是关于在Android中膨胀类按钮时出错的主要内容,如果未能解决你的问题,请参考以下文章

在 Xamarin 中膨胀类 android.support.design.widget.Coordinator 时出错

在 Android 平板电脑版本 4.4.2 中膨胀类 EditText 时出错

在列表适配器中膨胀类 com.google.android.youtube.player.YouTubePlayerView 时出错

使用 Android 膨胀类片段时出错

在 Android 4.4.2 上创建 TextInputLayout 时膨胀类 EditText 时出错:

Android Studio:膨胀类片段时出错