我一直在我的 Android 应用程序中使用 TextureView,它运行良好。就在最近,我在使用 Android API 25 (7.1.2) 的 Android 设备上测试了我的代码。相同的代码现在不起作用并引发错误,java.lang.UnsupportedOperationException: TextureView 不支持显示背景可绘制对象
。
我知道 void setBackgroundDrawable(可绘制背景)
是 deprecated for a long time ,现在它必须已被删除。但我什至不是自己设置的。
我正在使用最新的 buildTools 和 SDK。所以,我想知道为什么没有更新 textureView 内部实现。
这是相关的堆栈跟踪:
java.lang.UnsupportedOperationException: TextureView doesn't support displaying a background drawable
at android.view.TextureView.setBackgroundDrawable(TextureView.java:315)
at android.view.View.setBackground(View.java:18124)
at android.view.View.<init>(View.java:4573)
at android.view.View.<init>(View.java:4082)
at android.view.TextureView.<init>(TextureView.java:159)
at com.abdulwasaetariq.xyz.ui.customView.AutoFitTextureView.<init>(AutoFitTextureView.java:24)
at com.abdulwasaetariq.xyz.ui.customView.AutoFitTextureView.<init>(AutoFitTextureView.java:20)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[...]
at java.lang.Thread.run(Thread.java:745)
这是我如何使用我的(尚未定制的)自定义 TextureView:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.abdulwasaetariq.xyz.ui.activity.MainActivity">
<com.abdulwasaetariq.xyz.ui.customView.AutoFitTextureView
android:id="@+id/texture"
android:layout_width="1080px"
android:layout_height="1080px"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
这是我的相关 AutoFitTextureView.java: 在此处输入代码
public class AutoFitTextureView extends TextureView {
private int mRatioWidth = 0;
private int mRatioHeight = 0;
public AutoFitTextureView(Context context) {
this(context, null);
}
public AutoFitTextureView(Context context, AttributeSet attrs) {
this(context, attrs, 0); //(LINE#20)
}
public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); //(LINE#24)
}
public void setAspectRatio(int width, int height) {
if (width < 0 || height < 0) {
throw new IllegalArgumentException("Size cannot be negative.");
}
mRatioWidth = width;
mRatioHeight = height;
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (0 == mRatioWidth || 0 == mRatioHeight) {
setMeasuredDimension(width, height);
} else {
if (width < height * mRatioWidth / mRatioHeight) {
setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
} else {
setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
}
}
}}
所以,如您所见,异常发生在 super()
方法中,这意味着我的自定义 TextureView 不对这个异常负责。这是内线电话。
这是我的 gradle 配置:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.abdulwasaetariq.xyz"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
compile 'com.github.hotchemi:permissionsdispatcher:2.3.2'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.3.2'
}
知道为什么会发生这种情况吗? Android API 25 的任何发行说明,其中讨论了此更改?
最佳答案
以下是 View
源代码的 fragment 安卓牛轧糖:
/**
* Allow setForeground/setBackground to be called (and ignored) on a textureview,
* without throwing
*/
static boolean sTextureViewIgnoresDrawableSetters = false;
在单参数构造函数中(从所有其他构造函数中调用):
// Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
// On N+, we throw, but that breaks compatibility with apps that use these methods.
sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
在抛出异常的 View
构造函数中:
...
switch (attr) {
case com.android.internal.R.styleable.View_background:
background = a.getDrawable(attr);
break;
...
if (background != null) {
setBackground(background); // <--- this is the problematic line, apparently "background" is not null here
}
setBackground
的实际定义:
/**
* Set the background to a given Drawable, or remove the background. If the
* background has padding, this View's padding is set to the background's
* padding. However, when a background is removed, this View's padding isn't
* touched. If setting the padding is desired, please use
* {@link #setPadding(int, int, int, int)}.
*
* @param background The Drawable to use as the background, or null to remove the
* background
*/
public void setBackground(Drawable background) {
//noinspection deprecation
setBackgroundDrawable(background);
}
然后覆盖TextureView
中的setBackgroundDrawable
:
@Override
public void setBackgroundDrawable(Drawable background) {
if (background != null && !sTextureViewIgnoresDrawableSetters) {
throw new UnsupportedOperationException(
"TextureView doesn't support displaying a background drawable");
}
}
因此,您可以将以下所有内容拼凑起来:
1) 你有一个目标 SDK N (Nougat) - 从你的构建文件中很明显;
2) View
的构造函数确定非空背景(我暂时无法解释这部分)。
这就是成为一个实际问题所需要的一切。我没有看到您已设法在 xml 中定义可绘制对象,因此覆盖 setBackground
或 setBackgroundDrawable
似乎是解决我的问题的最明智的可能性。可能有另一种解决方法(或者“建议的用法”可能是一个更好的术语),您可以设法强制构造函数中的 background
变量保持为空。
关于安卓牛轧糖 : TextureView doesn't support displaying a background drawable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43705434/