2

I have recently completed a simple drag and drop shapes game. It had the user drag a shape (ImageView) to another "empty place holder" ImageView.

I now want to make this a little more advanced, instead of dragging a simple shape, I want to make a puzzle of various non-orthogonal shapes, for example breaking a circle into 5 different pieces. What I'm having a problem with right now is how to design the layout. I do not know how to make a truly "custom" shaped ImageView, as far as I can find from my research it's not possible. So my idea for now is to overlap a number of square ImageViews, each of which will have only a subset of an image and the rest transparent. Thus the final output will look like it's a number of custom shaped ImageViews.

Example:

enter image description here + enter image description here + enter image description here + enter image description here

Because only the internal sections are "visible" and the rest of the circle is transparent, when all of these pieces are placed in the same spot on the screen, the final image will look like:

enter image description here

I haven't tried this yet... but I foresee at least one problem. When I go to drag the pieces over to this puzzle, they will all "snap" into place when dragged to the same place. Because in reality all I really have here is a picture of a circle inside a ImageView which has some invisible rectangular boundary around it.

Hopefully this situation is clear. Now my questions:

  1. Is it possible to have truly custom shaped ImageViews instead of my idea of overlapping images?
  2. If what I'm thinking is the best way to handle this puzzle idea, then what property can be changed such that the "drop" action does not happen at the same place for all of these puzzle pieces? If I wanted to "drop" the pizza shaped piece, I'd like it to only snap into place when it go close to the top left of the circle.

Note: I am new to Android programming, and somewhat new to Java/XML as well, it’s very likely I’m overlooking something, so please feel free to suggest other approaches as you see fit.

Community
  • 1
  • 1
Mike
  • 47,263
  • 29
  • 113
  • 177
  • for a "layered" ImageView see my answer here http://stackoverflow.com/questions/16729169/how-to-maintain-multi-layers-of-imageviews-and-keep-their-aspect-ratio-based-on, HTH – pskink Sep 30 '13 at 17:02

2 Answers2

1
  1. Not really. Overlapping views is generally the way it's done. You could also use one View and override the drawing action yourself (multiple bitmaps drawn at relative locations within the View), but that would make the drag-drop aspect significantly harder.

  2. If the Views are all the same size, with the visible portions in the correct relative placement in each, they should snap together correctly. This is because the snap is (I believe) based on the position of the upper-left corner of the View. If the pizza-shaped piece's visible portion is correct with regards to that, it should snap in at exactly the right spot.

Geobits
  • 22,218
  • 6
  • 59
  • 103
  • 1. That makes me sad, but I kind of thought so. 2. Just for clarification, I'm saying if I take the "pizza" shaped piece, drag it up to the circle and "drop" on the bottom right of the visible circle it will probably "snap" into the correct upper left spot (because in reality I'm dragging one invisible `ImageView` square on to another). I *suspect* this is how it will work. But I only want that piece to snap in when it's dropped further towards the top left side where it belongs. Does that make sense? – Mike Sep 30 '13 at 16:36
  • I'm not clear on how you are handling the snapping. I assumed you were just checking the distance between "current" and "correct" placement, in relation the to the upper-left corner of each imageview. That way, you could just set whatever threshold you want. – Geobits Sep 30 '13 at 16:42
  • Maybe I should provide the code... but I have a `onDrag` method provided by a `OnDragListener` class, all of my "empty" drop targets register for it. What it does right now is on `getAction()`of `ACTION_DROP` it sets the `ImageView` of the drop "target" to the image of the draged `ImageView`. Basically I set `ImageView dropped = (ImageView) dragedView`. So I wasn't checking any boundaries before just using the hander to catch it. What is the property to check *where* something was dropped? Just check `dragedView.X` is within some `dropped.X` range? – Mike Sep 30 '13 at 18:58
  • You can also use `DragEvent#getX()` and `getY()` when you get the `ACTION_DROP` signal. I'm not sure if the dragged View's location updates while it's being dragged. – Geobits Sep 30 '13 at 19:09
0

So you have certain places you want to accept the drops, and I'm assuming you know their coordinates, say (d_x,d_y).

Then why not simply monitor the coordinate of the center (p_x,p_y) of image view of the piece you are dragging, say the "pizza" piece, and when the distance between the the piece and drop point is within an acceptable amount accept the drop.


But if you are asking if there is some way to make non-rectangular image views I don't believe that is possible.

However I don't think it is necessary in your case, because I believe even if you want them to drag the piece precisely into place you can calculate the coordinates where the draggable rectangle needs to go with knowledge of the shape of the piece and the assumption that the rectangle wraps the piece.

Emil Davtyan
  • 13,808
  • 5
  • 44
  • 66