Daniel Daniel - 3 months ago 54
Android Question

Prevent custom SurfaceView from drawing on top of other views

I have created a custom SurfaceView which I use to draw shapes, and the user can zoom and pan the view to interact with the shapes. This all works great, but the problem now is that the shapes will always be drawn on top of everything on my screen, also on top of other views such as buttons and textviews. I have tried ordering the custom view and my buttons in different ways in the XML layout, tried parenting the views to FrameLayouts and RelativeLayouts (as suggested here).

I would like to have buttons and other layout elements floating on top of my custom view. As seen in the image below, when I pan my view the rectangle will obscure the buttons.

How can I prevent my custom SurfaceView from drawing on top of everything?

enter image description here

My drawing code runs in a separate thread in the SurfaceView class:

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


My test XML layout, which I would expect to create a button (Left) which is behind the custom view and a button (Right) which is floating above the custom view, is:

<?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>

Answer

I'm facing a similar issue. I want to put transparent SurfaceView between another views which are being animated in RelativeLayout. When I do so, during animation views sometimes dissapear, sometimes only part of them is visible, it is weird. Then I discovered if I put SurfaceView to the layout first (so at the bottom) and then I call SurfaceView.setZOrderMediaOverlay(true), the content of SurfaceView is drawn at the bottom of the window, view are drawn on the top. If I put SurfaceView anywhere in the layout and then call SurfaceView.setZOrderOnTop(true), the content is always drawn on the top of the window (and also on the top of the views). If I put SurfaceView between views, its behavior is crazy, maybe it's because content of SurfaceView is drawn from separated thread and views are drawn from GUI (main) thread so they are "fighting" and that's why this behavior. Only way I found is drawing at the bottom or at the top. Try to create a new Fragment with transparent background where the SurfaceView is at the bottom as I described in first case and put that buttons you want to have above on top of it (so add them later in some RelativeLayout or FrameLayout) then show this fragment on the top of activity which holds content you want to have below it. Hopefully I helped a bit.

Comments