我如何保证我的Android SurfaceView是透明的而不是黑色的?

时间:2018-05-24 14:04:31

标签: java android android-layout

我有一个自定义视图,扩展SurfaceView覆盖我的界面的其余部分,它适用于模拟器,当调试器连接到我的手机上时,但是当手机在电池上运行时,视图永远不会清除。

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;
    }

}

我知道这里的一些调用是多余的 - 这主要是尝试许多不同的东西来尝试使其工作的遗产。您会注意到我已经完成了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中提取的:

@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);
}

我尽可能地尝试简化这一点,显然在这种情况下会发生更多事情,但希望这足以说明问题可能来自哪里。

AutoFitTextureView正在显示相机的视图。

  • 当我在模拟器中运行它时,一切都按预期显示, 无论电池设置如何。
  • 当我在通过USB连接的手机上运行时,一切都按预期显示。
  • 当我在断开连接的手机上运行时,视图通常(但不总是)显示为纯黑色 - AutoFitTextureView完全被遮挡,但CustomView上的线条被绘制出来。其他组件 可见,这让我怀疑我何时或如何调用setZOrderOnTop()时出现问题。
  • 如果我在片段中点击断点并将CustomView的可见性设置为INVISIBLE,我可以立即看到其他所有内容,但正如您所料,我会丢失叠加层。此时手动呼叫setZOrderOnTop似乎无法改变任何内容。
  • 当它正确运行时,我可以使用布局检查器工具检查结构,但是当SurfaceView不透明时,布局检查器会引发Unexpected Error: Empty View Hierarchy消息。我还没能在Logcat中找到相应的错误消息。

如何确保SurfaceView派生的View始终透明?如果我无法保证,是否有任何方法可以测试当前 是否透明,以便我可以进行调解?

1 个答案:

答案 0 :(得分:0)

认为我现在已经解决了这个问题,问题在于我试图将TextureView派生类型放在AutofitTextureView派生类型上。关闭显示相机预览的另一个SurfaceView的{​​{1}}似乎已经成功了。