使用selectableItemBackground时的android.view.InflateException

时间:2015-10-29 08:32:03

标签: android android-layout android-view android-attributes

在给我的布局充气时,我得到了这个例外:

E AndroidRuntime: android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
E AndroidRuntime:        at com.myapp.view.MyRecyclerAdapter.onCreateViewHolder(MyRecyclerAdapter:80)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5288)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4551)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461)
E AndroidRuntime:        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1962)

日志中没有“由...引起”,但我添加了代码来捕获异常并调用getCause()直到它返回null,这是事件序列:

android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
android.view.InflateException: Binary XML file line #11: Error inflating class <unknown>
Error: Binary XML file line #11: Error inflating class <unknown>
android.content.res.Resources$NotFoundException: File res/drawable-v11/selectable_list_background.xml from drawable resource ID #0x7f020096
java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}

0x7f020096是selectable_list_background(见下文),它引用的TypedValue是?selectableItemBackground

我将异常范围缩小到使用?selectableItemBackground。更具体地说,我正在使用CardView:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/selectable_list_background"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp"
    >

这是drawable/selectable_list_background的相关部分:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?selectableItemBackground" />
</selector>

此活动使用我自己的主题,其父级为Theme.AppCompat.Light.NoActionBar

这段代码以前有用,但是我在几个月后挖出了这段代码,现在它崩溃了。我的猜测是,这与将支持库升级到23.0.1并将SDK定位到23有关,但我还没有切换回22来验证。

如果删除引用?selectableItemBackground的一行,一切正常。我还尝试了?attr/selectableItemBackground?android:attr/selectableItemBackground,但得到了相同的结果。 (后者让我相信它可能不是支持库的问题。)

修改

我在调试器中查看了它,我怀疑android.content.res.ResourcesloadDrawable()中的代码是这个代码:

Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
    [...]
    dr = loadDrawableForCookie(value, id, null);

请注意,此函数采用主题,但在调用loadDrawableForCookie()时不会传递它,这是最终触发第一个异常的方法:

java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}
    at android.content.res.TypedArray.getDrawable(TypedArray.java:867)
    at android.graphics.drawable.StateListDrawable.inflateChildElements(StateListDrawable.java:170)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:115)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1215)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1124)
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2630)
    at android.content.res.Resources.loadDrawable(Resources.java:2540)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
    at android.view.View.<init>(View.java:4280)

此代码似乎是Android 6.0的新功能 - 5.0代码完全不同,但主题在加载drawable时传入。主题是必要的AFAICT - 有问题的属性是AppCompat的一部分,因此它需要活动的主题来解决它。

这似乎是一个明显的错误,所以我不相信我在这里是正确的轨道。有什么想法吗?

4 个答案:

答案 0 :(得分:5)

官方回答 - 您无法使用android:drawableandroid:src属性的主题属性。根据设计,根本不可能。还有另一个答案探讨了同一个问题并提供了解决方案:How to reference style attributes from a drawable?

在我的情况下,我无法真正做到这一点,因为AppCompat的?selectableItemBackground引用了私有的drawable。所以我选择了一个代码解决方案 - 我在未选择卡时将前景设置为?selectableItemBackground,并且在我处于选择模式时将其设置为我自己的状态列表。

这是一个非常丑陋的解决方案,如此丑陋以至于我不打算在这里分享代码,但到目前为止我能想出的最好的代码。如果有人有更好的解决方案,我很乐意听到。

答案 1 :(得分:5)

正如@Artjom所说,问题在于在创建自定义视图时传递 let redirectURI = "https://www.instagram.com/" let clientID = "{YOUR_CLIENT_ID}" let clientSecret = "{YOUR_CLIENT_SECRET}" let code = "{RECEIVED_CODE}" let urlString = "https://api.instagram.com/oauth/access_token" let url = NSURL(string: urlString)! let paramString = "client_id=\(clientID)&client_secret=\(clientSecret)&grant_type=authorization_code&redirect_uri=\(redirectURI)&code=\(code)&scope=basic+public_content" let request = NSMutableURLRequest(URL: url) request.HTTPMethod = "POST" request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)! let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in do { if let jsonData = data { if let jsonDataDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) as? [String: AnyObject] { NSLog("Received data:\n\(jsonDataDict))") } } } catch let err as NSError { print(err.debugDescription) } } task.resume() 。我也遇到了同样的问题,我正在传递application context而不是getApplicationContext()作为activity。传递context后,Activity问题已解决。

希望它对其他人有帮助。

答案 2 :(得分:1)

不幸的是,其他答案不是我的情况。为我工作的方法是检查您的活动是否使用AppCompat主题样式:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
    </style>

然后在您的活动中使用AppCompat主题(在很多方面,但我展示了使用Manifest的方式):

<application
        android:name=".Abbott"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

    <!-- Any configuration inside -->

</application>

答案 3 :(得分:0)

使用androidx Fragment Testing组件时出现相同的错误。默认情况下,launchFragmentInContainer()使用主题FragmentScenarioEmptyFragmentActivityTheme,从而导致错误。

简单的解决方法是使用您自己的主题来扩展AppCompat:

launchFragmentInContainer(theme = R.style.AppTheme)