如何保证我的Android SurfaceView是透明的而不是黑色? [英] How do I guarantee that my Android SurfaceView is transparent instead of black?

查看:92
本文介绍了如何保证我的Android SurfaceView是透明的而不是黑色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义视图,该视图扩展了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 the CustomView is drawn. The other components are visible, which leads me to suspect there is a problem with when or how I call setZOrderOnTop().
  • If I hit a breakpoint in the fragment and set the visibility of the CustomView to INVISIBLE I can immediately see everything else, but as you might expect I lose the overlay. Manually calling setZOrderOnTop 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆