Getting Touch events "underneath" a ScrollView with Transparency?

Hi there. Well, my first app/game is taking shape and I’m finding Corona/Solar/Lua a fine environment to code in. Most questions I’ve had along the way get answered with an easy forum search and ample sample code to clarify.

Can’t quite solve the latest one though, in spite of attempted searches. I think the answer might involve masks, but I’m not quite sure what to mask exactly.

So I’ve got a scrollView acting as a “top Layer” in my game. Kind of a frame for the stuff underneath, which moves in parallax based on where the scrollView has been scrolled to. This top layer has “windows” of transparency that let us see those layers underneath, pushed toBack() to be underneath the scrollView. Visually, it all works, and these layers’ position can be shifted depending on where the user has scrolled the scrollView.

BUT I can’t seem to attach a “touch” listener to any of the items “underneath” the scrollView and successfully get those touch events. I only get those events if I bring those layers above the scrollView, which of course is illogical in a layering sense. How can I make the “windows” in my scrollView act transparent to touch? So that I can touch items underneath? I tried attaching a mask on the bitmaps making up the scrollView, but that didn’t seem to work.

I feel like I’m missing something fairly simple here, but so far the exact search I’m looking for has eluded me.

Cheers,
zane

Might should have mentioned that the scrollView frames with transparency are drawn using JPEG 2000 images so they have transparency and yet are way smaller than PNGs. I kinda wonder whether the lossy nature of these alphas is keeping the “windows” from being 100% transparent or something. (But I kinda think it must be something else. I could always try PNGs to confirm, I guess.)

Hi Zane,

On your scrollView listener, if you have a “return false/true” (or any return for that matter), then the touch/tap events will end there. ScrollView acts as a whole single piece of object even if you have “windows” to see through them. So, if that’s the case then remove the return entry and the events will be triggered through anything listening underneath.

Without having a visual of what you’re trying to do I’m not sure whether you’re complicating things or this is indeed a good approach. :slightly_smiling_face:

Nevertheless, you can also dispatch your own events, or even call the function you want to call by the suppose touching of the objects underneath the scrollView. This is accomplished by checking whether the touch event x and y coordinates are within the boundaries and x /y locations of the object underneath.

@rzanerutledge,
Have you solved the problem yet? If you have, please help to share so that the rest of us in the community can learn from it.

You have an interesting use-case for “scrollView” widget, where you have “stuff” display objects below the “scrollView”, yet the objects below seem to need to receive “touch” events.

Some questions to seek more clarity on your usage.

  • Are those “stuff” display objects move together with the scrolling action on the “scrollView”? or are they static?
  • You mentioned you are using an image with transparency in “JPEG2000” format. How do you do that in display.newImage() or display.newImageRect()?
  • This “JPEG2000” image is in fact, a layer on top of the scrollView. Is it “inserted” into the scrollView and move with the scrolling movement? Is this image a fixed image or if it changes?

Thanks.

Hi @luantiang. Thank you for the response.

No, I actually haven’t solved my problem yet. I tried removing the return(true) statement from my scrollListener, but that didn’t seem to allow the touch events to reach the touch listeners “below” my scrollView, even through the “windows.”

To answer your other questions: the “stuff” display objects below the scrollView don’t move “with” the scrollView exactly, but they do move based on the current position of the scrollView. (They move less and at different rates, depending on their depth, so that it looks like a landscape moving in “parallax” out beyond the window.) If you’ve played the game Device 6, they use a very similar technique, though they don’t need to interact with the objects beneath the scrollView.

The images (JPEG2000) on the scrollView are placed there with display.newImageRect() and scrollView:insert(). And yes, it does move with the scrollView. It is mostly fixed for each “load/stage” of the game, although solving puzzles may cause it to be refreshed/updated somewhat from time to time.

I appreciate your assistance!

If I can’t figure out a logical way to access touch events “below” the scrollView, my workaround plan is to “connect” a fully transparent newImageRect on top of the scrollView to the newImageRect I intend to move below the view, and have it’s position update to “follow” the other. It’s a clunky workaround, and probably unnecessarily complex, but right now it’s kinda all I’ve got (other than Juni’s closing paragraph suggestion, which I haven’t quite figured out how to code yet).

Thanks for your detailed response. It certainly gives a better idea of you are trying to achieve. Just one other question, broken into multiple parts below,

  • You mentioned your “stuff” display objects below the scrollView do move based on the current position of the scrollView. How do you “connect” scroll events in scrollView with the “stuff” display objects"?
  • What I meant was, what “connect” mechanism do you use to send “events” from scrollView to the “stuff” display objects to get the “stuff” to move when scrollView is scrolling?
  • or are you using “enterFrame” events?

The reasons why this is key,

  • You can consider using the same “connect” mechanism to move your “JPEG2000” image too (with different calculation), without the image being “inserted” into scrollView.
  • This would give you the flexibility of different layering configuration of display objects.

For example, your current layers of display objects are,

  • “JPEG2000” image on top layer, which does not seem to need to receive “touch” event, but moved with scrollView’s scrolling, since it is “inserted” into scrollView.
  • scrollView in the middle layer, which require “touch” event to scroll and etc,
  • “stuff” at the bottom layer, which require “touch” events, but cannot so do right now, as it is below the scrollView.

If your “connect” mechanism works for you, can be extended to the “JPEG2000” image, then you could have the following possible layers of display objects.

  • “JPEG2000” image on top layer, does not need “touch” event, but moved by “connect” mechanism, with scrollView,
  • “stuff” display objects in the middle layers, can now receive their “touch” events, and continue to to move with scrollView by your “connect” mechanism.
  • scrollView at the bottom layer, receive the “touch” event to move by “connect” mechanism, the above two layers, as well as to scroll whatever display objects “inserted” into scrollView.

Of course, I am making an assumption of your “connect” mechanism. It would be clearer for us (the community) to know once you share details of this “connect” mechanism.

Interesting.

And perfectly understandable response. Let me elaborate a little.

My “stuff” I call BGViews, and they are updated with UpdateBGViews() inside my onFrame() listener, which is a Runtime “enterFrame” listener, so yeah, pretty much checking this every basic cycle. Inside that, I basically check the scrollView:getView() current Y position, and if we are looking through a window, adjust the offset Y for each of the BGView layers visible through the window based on how far we’ve moved in the scrollView.

I certainly could do the same thing for the Foreground JPEG2000 images which contain the windows in their artwork and push the actual scrollView to the bottom, but I guess I originally worried about lag or unsmoothness. Also, those are BIG images (compared to what we’re seeing out the “windows”) and they don’t need to move in a sophisticated manner, just all together with the scrollView, and smoothness is important, since there is readability involved. (It is kinda like an eBook with “windows” being pictures, much like Device 6 in basic layout, but…well, different). In fact, in the @4 case, the images are 4096 pixels tall x 4 of them, for a scrollView height of 16,384 per “page/load screen.” I split them into 4 pieces because of JPEG size limitations and at load time put them back together in the scrollView in sequence.

I guess I was concerned with keeping them connected or them not updating correctly if I simply use a “connection mechanism” like I am with the views behind. (On extreme scrolling of the scrollView, I do notice the BGViews aren’t always updated quite as smoothly as the scrollView is.) I can try your scheme, but I think that was my original thinking. (Well, that and the fact that I was just learning lua and Corona as I went, so the big scrollView kinda came first.)

I’m guessing in your proposed order, I’d need to at least put a filled Rectangle in the scrollView to define its height and have something to receive the touches at the bottom? (Some of my pages are not the full 16,384 height and if I don’t put those newImageRects in there, it only scrolls as far as I’ve defined/filled, which is handy.)

I can try to decouple the JPEG2000s from the scrollView and connect them and see if the update behavior is smooth enough. (Realistically, I could also check to see if they are even “on screen” and only update the Y position for the 2 of the 4 images that will be visible at any given time, which might improve performance over updating all 4, if there is danger of adding any lag between them.)

So, yes, my “connect” mechanism is pretty brute-force, in terms of checking the Y values of the scrollView and updating Y positions of BGView layers as needed. (I also do other tricks to them, like skew and scale, depending on whether I’m faking depth or perspective. It’s a little more complex than Device 6.)

So I think your proposal would work IF the updates to those images are always fast enough for a smooth scroll, compared to letting the scrollView handle moving those things.

z

Did you try tap or touch listener? Tap works for me, I also had problems with touch for the elements in a scrollview.

1 Like

@Odisej,

Yes. “tap” event would work for display objects below the scrollView, since scrollView intercepted only “touch” events. Thanks for pointing it out. This is an instance of usage where “tap” event is really needed.

@rzanerutledge,

Here is another possible solution for you, as suggested by Odisej. It is a more efficient solution.

Of course, “tap” event does not have “event.phase” as “touch”, but you may not need it anyway for “BGViews”.

A “tap” event won’t work, as I’m needing the user to drag objects from one point to another to solve puzzles. So I don’t see that being a viable solution here for me. (Sorry I didn’t clarify that.)