如何保证我的Android SurfaceView是透明的而不是黑色? [英] How do I guarantee that my Android SurfaceView is transparent instead of black?
问题描述
我有一个自定义视图,该视图扩展了SurfaceView
并覆盖了我的其余界面,它适用于仿真器以及调试器连接到手机上的情况,但是当手机使用电池运行时,该视图永远不会消失.
I have a custom view that extends SurfaceView
overlaying the rest of my interface, it works on emulators and when the debugger is connected on my phone, but but when the phone is running on battery the view never clears.
public class CustomView extends SurfaceView {
private final Paint paint;
private final SurfaceHolder holder;
private final Context context;
private float strokeWidth = 4;
private boolean canvasAlreadyLocked = false;
public CustomView(Context viewContext, AttributeSet attrs)
{
super(viewContext, attrs);
Log.i("CustomView", "CustomView create context & attrs");
holder = getHolder();
context = viewContext;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
drawLine();
setZOrderOnTop(true);
holder.setFormat(PixelFormat.TRANSPARENT);
}
public void resume() {
Log.i("CustomView", "Resume the customview display.");
setZOrderOnTop(true);
holder.setFormat(PixelFormat.TRANSPARENT);
}
@Override
public void onAttachedToWindow(){
super.onAttachedToWindow();
setZOrderOnTop(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
protected void drawLine() {
if (!canvasAlreadyLocked) {
invalidate();
if (holder.getSurface().isValid()) {
try {
final Canvas canvas = holder.lockCanvas();
canvasAlreadyLocked = true;
if (canvas != null) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(strokeWidth * 2);
canvas.drawLine(0, getY(), getWidth(), getY(), paint);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(strokeWidth);
canvas.drawLine(0, getY(), getWidth(), getY(), paint);
holder.unlockCanvasAndPost(canvas);
canvasAlreadyLocked = false;
}
}
catch (IllegalArgumentException iae)
{
Log.w("CustomView", "Exception trying to lock canvas: "+iae.getMessage());
Log.getStackTraceString(iae);
}
}
}
}
private float getY() {
getHeight()/2;
}
}
我知道这里的一些调用是多余的-大多数情况下都是尝试多种不同的方法以使其正常工作的遗产.您会注意到,我已经完成了此答案中推荐的所有操作.
I'm aware that some of the calls here are redundant - that is mostly the legacy of trying lots of different things to try to make it work. You will notice that I have already done everything recommended in this answer.
布局如下:
<FrameLayout 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="com.custom.CustomViewApp">
<FrameLayout
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true">
<com.custom.AutoFitTextureView
android:id="@+id/texture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<ImageButton
android:id="@+id/gpsNotification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gps_unfixed"
android:layout_gravity="right"
android:tint="@color/gps_unfixed"
android:background="@null" />
<ProgressBar
android:id="@+id/camera_spinner"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:gravity="center"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="invisible"
/>
<com.custom.CustomView
android:id="@+id/custom_view"
android:background="@color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</FrameLayout>
</FrameLayout>
这是从ViewFragment中拉进来的:
This is pulled in from a ViewFragment:
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
gpsNotification = (ImageButton) view.findViewById(R.id.gpsNotification);
customView = (CustomView) view.findViewById(R.id.custom_view);
spinner = (ProgressBar) view.findViewById(R.id.camera_spinner);
spinner.setVisibility(VISIBLE);
}
我已尽力简化了这一过程,显然在这种情况下还会发生很多事情,但是希望这足以表明问题可能来自何处.
I have tried to simplify this as far as I can and obviously there is a lot more happening in this scenario, but hopefully this is enough to indicate where the problem might be coming from.
AutoFitTextureView
正在显示摄像机的视图.
The AutoFitTextureView
is displaying the view from the camera.
- 当我在模拟器中运行它时,一切都会按预期显示, 无论电池设置如何.
- 当我在通过USB连接的手机上运行它时,一切都会按预期显示.
- 在断开连接的手机上运行该视图时,视图通常(但不总是)显示为纯黑色-
AutoFitTextureView
被完全遮盖,但是绘制了CustomView
上的线.其他组件 是可见的,这使我怀疑何时或如何调用setZOrderOnTop()
存在问题. - 如果我在片段中命中了一个断点并将
CustomView
的可见性设置为INVISIBLE
,我可以立即看到其他所有内容,但是正如您可能期望的那样,我会丢失叠加层.此时手动调用setZOrderOnTop
似乎没有任何改变. - 当它正常运行时,我可以使用布局检查器"工具检查结构,但是当SurfaceView不透明时,布局检查器"会发出一条
Unexpected Error: Empty View Hierarchy
消息.我无法在Logcat中找到相应的错误消息.
- When I run it in an emulator, everything displays as expected, regardless of the battery settings.
- When I run it on my phone connected by USB everything displays as expected.
- When I run it on my phone disconnected, the view will usually, but not always, show as plain black - the
AutoFitTextureView
is completely obscured, but the line on theCustomView
is drawn. The other components are visible, which leads me to suspect there is a problem with when or how I callsetZOrderOnTop()
. - If I hit a breakpoint in the fragment and set the visibility of the
CustomView
toINVISIBLE
I can immediately see everything else, but as you might expect I lose the overlay. Manually callingsetZOrderOnTop
at that point doesn't seem to change anything. - When it is running correctly, I can examine the structure with the Layout Inspector tool, but when the SurfaceView is opaque the Layout Inspector raises an
Unexpected Error: Empty View Hierarchy
message. I haven't been able to locate a corresponding error message in Logcat.
如何确保我的SurfaceView派生视图始终是透明的?如果我不能保证,有什么办法可以测试当前 是否透明,以便在不透明的情况下进行诉求?
How do I ensure my SurfaceView-derived View is always transparent? If I can't guarantee that, is there any way I can test whether it currently is transparent so that I can intercede if it is not?
推荐答案
我认为现在,我已经解决了这个问题,问题是我试图将SurfaceView
派生类型放在TextureView
派生类型.将AutofitTextureView
换成另一个显示摄像机预览的SurfaceView
似乎可以解决问题.
I think I have now solved this and the problem was that I was trying to put a SurfaceView
derived type over a TextureView
derived type. Switching out the AutofitTextureView
for another SurfaceView
showing the camera preview seems to have done the trick.
这篇关于如何保证我的Android SurfaceView是透明的而不是黑色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!