我创建了一个用于绘制形状的自定义SurfaceView,用户可以缩放和平移视图以与形状进行交互。这一切都很有效,但现在的问题是形状总是在我的屏幕上的所有之上绘制,也可以在其他视图(如按钮和textview)之上绘制。我尝试在XML布局中以不同的方式排序自定义视图和我的按钮,尝试将视图父级化为FrameLayouts和RelativeLayouts(as suggested here)。
我想将按钮和其他布局元素浮动在我的自定义视图之上。如下图所示,当我平移视图时,矩形会遮挡按钮。
如何阻止我的自定义SurfaceView绘制在所有内容之上?
我的绘图代码在SurfaceView类的一个单独的线程中运行:
public class CustomShapeView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
/* Other implementation stuff */
@Override
public void run() {
while (isDrawing) {
if (!holder.getSurface().isValid())
continue; //wait till it becomes valid
Canvas canvas = null;
try {
canvas = holder.lockCanvas(null);
synchronized (holder) {
try {
lock.lock();
canvas.concat(sampleMatrix);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawShapes(canvas);
} finally {
lock.unlock();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
}
我的测试XML布局,我希望创建一个位于自定义视图后面的按钮(左)和一个浮动在自定义视图上方的按钮(右):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Left"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.CustomShapeView
android:id="@+id/floor_plan_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right"
android:id="@+id/button2"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</RelativeLayout>
答案 0 :(得分:4)
在我的代码中,我调用函数setZOrderOnTop(true);
,确保表面视图始终绘制在所有内容之上。这段代码由前一个开发人员保留,以便为画布提供自定义背景,而不是仅使用纯色。使用SurfaceView,可以在为画布设置自定义背景或在画布顶部绘制视图之间进行权衡。
选项是
setZOrderOnTop(true);
可以有自定义背景,但没有重叠视图。setZOrderOnTop(false);
可以覆盖视图但只有纯色背景(通过调用例如canvas.drawColor(Color.WHITE);
来清除绘制调用之间)。我选择了第二个选项,因为我重视在自定义背景上覆盖视图。
答案 1 :(得分:2)
我面临类似的问题。我想在SurfaceView
中设置动画的其他视图之间添加透明RelativeLayout
。当我这样做时,在动画视图中有时会消失,有时只有部分可见,这很奇怪。然后我发现我是先将SurfaceView
放到布局上(所以在底部),然后我调用SurfaceView.setZOrderMediaOverlay(true)
,在窗口底部绘制SurfaceView
的内容,视图是画在上面。如果我将SurfaceView放在布局中的任何位置然后调用SurfaceView.setZOrderOnTop(true)
,则内容始终绘制在窗口的顶部(也位于视图的顶部)。如果我在视图之间放置SurfaceView
,它的行为是疯狂的,也许是因为SurfaceView
的内容是从分离的线程中提取的,而视图是从GUI(主)线程中提取的,因此它们是&# 34;战斗&#34;这就是为什么这种行为。我发现的唯一方法是在底部或顶部绘制。尝试创建一个透明背景的新Fragment
,其中SurfaceView
位于底部,正如我在第一种情况下所描述的那样,并将您想要的按钮放在上面(所以稍后将其添加到某些按钮中) RelativeLayout
或FrameLayout
)然后将此片段显示在活动的顶部,该活动包含您希望在其下方拥有的内容。希望我帮了一下。