1

I'm trying to implement a custom view in which the user can draw with his finger. Basically, I'm following this tutorial.

Everything seems to be working nice, but, given the fact that I also have 2 buttons underneath the custom view like so:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background_color"
    tools:context=".MainActivity" 
    android:id="@+id/mainScreen" >

    <Button
        android:id="@+id/buttonSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:text="@string/save" />

    <Button
        android:id="@+id/buttonQuery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:text="@string/query" />

    <com.example.myapp.DrawView
        android:id="@+id/drawView"
        android:background="@color/red"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/buttonSave" />

</RelativeLayout>

it actually draws even underneath the buttons and I'm having a hard time understanding why it doesn't capture only the touch events that occur on the DrawView and not outside it. Basically, I can't start the line from above the buttons, but once I start drawing on my view, I can even extend the line outside of it.

As far as I can tell, the DrawView doesn't overflow beneath the buttons, as discussed here so I want to figure out what's going on. Do I really have to check if the events are out of bounds? Does it actually delegate all of the touch events to the currently focused view? Is there any way to change this behavior?

This simple tutorial doesn't have the described issue, but it draws point by point.


Update: Debugging the application, I determined that drawView has size 480x728, while mainScreen has 480x800, so they do not overlap. It continues to register touch events even if they are triggered outside of the drawView, once it has focus. This is what I'm trying to avoid and it would be nice to do it without passing the event coordinates through a big if statement...

Community
  • 1
  • 1
Mihai Todor
  • 8,014
  • 9
  • 49
  • 86

2 Answers2

0

If you don't want the buttons to overlap the DrawView then use a LinearLayout to keep all of the Views separate. At the moment, judging from the XML layout (and assuming there isn't anything funky going on with the layout programmatically in code), your buttons are overlapping the DrawView.

I'm under the impression you're after having the two buttons placed at the top side by side, with the DrawView filling the remaining screen area underneath. To do this, use an outer container LinearLayout with vertical orientation. The first child of it is another LinearLayout with horizontal orientation, containing the two buttons. The second child of the inner LinearLayout is the DrawView. Use width, height, and weight attributes to get desired dimensions. (Or, another way is to keep the XML layout structure you have, but set some top margin on the DrawView to equal the buttons' height, which could be fixed in the XML layout, or done programmatically.)

EDIT Sorry, I totally missed the layout_above attribute, which invalidates my second sentence. In that case, without being able to fire up Eclipse at the moment I'm not sure. Try the LinearLayout approach as suggested anyway.

Trevor
  • 10,903
  • 5
  • 61
  • 84
  • I just debugged it and it does not overlap at all. The drawView has size 480x728, while mainScreen has 480x800. It continues to register touch events even if they are triggered outside of the drawView, once it has focus. This is what I'm trying to avoid and it would be nice to do it without passing the event coordinates through a big `if` statement... – Mihai Todor Jul 31 '12 at 16:54
  • Silly question perhaps, but how are you determining that it is capturing `MotionEvent`s and drawing *underneath* the buttons? Do your buttons have transparency? – Trevor Jul 31 '12 at 17:22
  • Actually, it's really weird, because I don't understand on what does it draw. I mean, shouldn't the canvas that is passed to onDraw have the same size as my drawView? I haven't assigned any color to the button, so, by default, they are transparent. – Mihai Todor Jul 31 '12 at 17:33
  • Indeed, the canvas has size 800, same as mainScreen. Do you have any idea why? – Mihai Todor Jul 31 '12 at 17:35
  • OK, I found out why: http://stackoverflow.com/questions/10954798/why-canvas-is-not-the-same-size-as-view-in-ondraw-android but this still doesn't explain the events issue. I will try to just ignore the events triggered outside the bounds of drawView for now. – Mihai Todor Jul 31 '12 at 17:46
  • I'm pretty sure that the differences discussed in that question you linked to are actually due to screen density (see how he mentions a 1.5 factor). It so happens that one of my earliest own SO questions related to this. In your case, I am starting to question how you have determined that `drawView`'s height really is 800px. Where and how did you make the measurement? Try drawing a border on the `canvas` in the `onDraw()` to show where its bounds are, using the following coordinates to draw the rectangle: `0, 0, getWidth(), getHeight()` and using a `Paint` with a stroke width of several `px`. – Trevor Jul 31 '12 at 17:56
  • Relating to the question you linked to, here is my very own question from a while back that seems oddly related to it: http://stackoverflow.com/questions/6286483/in-the-ondraw-method-why-does-the-supplied-canvas-already-have-scale. I don't think this is anything to do with your situation, though; if your `drawView` can accept `MotionEvent`s and can visibly draw under those buttons, I can't believe it isn't actually occupying the space beneath them. Hence the suggestion to draw a border, or ensure you're `Log`ging a call to `getHeight()` during the `onDraw()` perhaps. – Trevor Jul 31 '12 at 18:01
  • Yeah, so basically the canvas that is sent to onPaint has the same size as my #mainScreen, while the #drawView ends above the buttons. I tested this as you suggested, by drawing a rectangle in the onPaint method of my custom view. I don't think it's the same issue as yours and anyway, this is not the biggest issue in my case. – Mihai Todor Jul 31 '12 at 18:09
  • What was the result of drawing the rectangle border, whose height / width is from `getWidth()` / `getHeight()`? Where did you see the border on the screen? Edit: Ah ok, reading again I think you're saying that the border indicates the `drawView` does `not` overlap the buttons. In that case I'm getting quite stumped! – Trevor Jul 31 '12 at 18:11
0

This turned out to be some weird bug in the way the Android emulator displays the interface. It may do something similar on real devices (throwing touch events even outside of the listener view), but since it limits the display to the drawView, I can safely ignore them for my application, since I just need to extract the drawn shape from the drawView. It may cause big headaches in other applications, though...

Mihai Todor
  • 8,014
  • 9
  • 49
  • 86