Slide menu

I've searched the forums for this, but I can't think what it's called, so haven't found what I need - apologies if it's already out there!

I need to make a sliding menu - similar to the level selectors in Blast Monkey, Cavern Drake, Angry Birds... It's not for a game but for a different app I'm producing for a client.

Any ideas if there's a tutorial or block of sample code out there?

Cheers
Steve

something like this,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
local menus = {}
local num = 7
local xPosHandler = {}
local function handleTouch(e)
        local phase = e.phase
        local t = e.target
        if "began" == phase then
                for i=1,num do
                        xPosHandler[i] = e.x - menus[i].x
                end
                display.getCurrentStage():setFocus(t)
                t.isFocus = true
        elseif "moved" == phase and t.isFocus  then
                for i=1,num do
                        menus[i].x = e.x - xPosHandler[i]
                end
        elseif "ended" == phase then
                display.getCurrentStage():setFocus(nil)
                t.isFocus = false
                
                
        end
end
for i=1,num do 
        menus[i] = display.newRect(0,0,100,100)
        menus[i].x = i * 150
        menus[i].y = 160
        menus[i].myName = i
        menus[i]:addEventListener("touch",handleTouch)
end

one more,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
local centerPos = display.newRect(0,0,120,120)
centerPos.x = 240
centerPos.y = 160
centerPos:setFillColor(0,255,0,200)
local menus = {}
local num = 7
local xPosHandler = {}
local function handleTouch(e)
        local phase = e.phase
        local t = e.target
        if "began" == phase then
                for i=1,num do
                        xPosHandler[i] = e.x - menus[i].x
                end
                display.getCurrentStage():setFocus(t)
                t.isFocus = true
        elseif "moved" == phase and t.isFocus  then
                for i=1,num do
                        menus[i].x = e.x - xPosHandler[i]
                end
        elseif "ended" == phase then
                display.getCurrentStage():setFocus(nil)
                t.isFocus = false
                for i=1,num do
                       if menus[i].x > 240 - 80 and  menus[i].x < 240 + 80 then
                                diff  = menus[i].x - 240
                       end
                end
                
                for i=1,num do
                        transition.to(menus[i],{x = menus[i].x - diff,time = 500})
                end
                
        end
end
for i=1,num do 
        menus[i] = display.newRect(0,0,100,100)
        menus[i].x = 90 + i * 150
        menus[i].y = 160
        menus[i].myName = i
        menus[i]:addEventListener("touch",handleTouch)
end

Thanks hgvyas123! That's really helpful.

I'll give these a try and let you know if I have any probs!

S

sure

:)

Perfect, thank you for the example.

How is it possible to only "mask/show" the area inside the green rectangle, so outside the green rectangle the white rectangle are invisible/hidden?

Wow thank you very much! really good example

@timwills :- this will give some idea

and thanks to all for saying me thanks :-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
local centerPos = display.newRect(0,0,120,120)
centerPos.x = 240
centerPos.y = 160
centerPos:setFillColor(0,255,0,200)
 
 
 
local menus = {}
local num = 7
local xPosHandler = {}
local function handleTouch(e)
        local phase = e.phase
        local t = e.target
        if "began" == phase then
                for i=1,num do
                        xPosHandler[i] = e.x - menus[i].x
                end
                display.getCurrentStage():setFocus(t)
                t.isFocus = true
        elseif "moved" == phase and t.isFocus  then
                for i=1,num do
                        menus[i].x = e.x - xPosHandler[i]
                        menus[i].alpha = 0.3
                                                if menus[i].x > 240 - 80 and  menus[i].x < 240 + 80 then
                                                        menus[i].alpha = 1
                                                end
                end
        elseif "ended" == phase then
                display.getCurrentStage():setFocus(nil)
                t.isFocus = false
                
                for i=1,num do
                           menus[i].alpha = 0.3
                       if menus[i].x > 240 - 80 and  menus[i].x < 240 + 80 then
                                diff  = menus[i].x - 240
                                menus[i].alpha = 1
                       end
                end
                
                for i=1,num do
                        transition.to(menus[i],{x = menus[i].x - diff,time = 500})
                end
                
        end
end
 
 
 
for i=1,num do 
        menus[i] = display.newRect(0,0,100,100)
        menus[i].x = 90 + i * 150
        menus[i].y = 160
        menus[i].myName = i
        menus[i]:addEventListener("touch",handleTouch)
                menus[i].alpha = 0.3
                if menus[i].x == 240 then
                        menus[i].alpha = 1
                end
end

@ hgvyas123 - very nice! Thanks! :)

Jay

welcome always happy for inspiration see :)

@ hgvyas123 - Thanks very much for your example!

I looked at the example. Great thinking,thanks! But technically there's no clipping/masking, but a rectangle object pops in when it's close to the center, while the rest are set to hidden objects.

Is this the way to go when making a enterFrame mini imagescroller that is also draggable/slidable?

ps. So far, thanks for the help, Corona is really great!

mini imagescroller ???

I'm sorry, english isn't my native language. Maybe imagescarousel or imagesslider is a better word for it?

See it as an imageslider where you can slide through your images with slide gestures. Plus arrow-buttons to the left and the right of the rectangle that have a "tap"-event on it.

So your example was great, but the images sort of pop-in and pop-out.

My question is: Is it possible to create a clipping mask to the centerPos Rectangle, so the pop-in/pop-out doesn't occur while the rest of the screen around the rectangle can be filled with other objects. Like this it becomes sort of a widget.

I found a javascript look-alike for the question I have, only without the slide/drag event: javascript example

You see that the images are in a sort of clipping mask.

You don't have to do any clipping, just look where the alpha is being set to 0.3 and change that to 0. Now the objects on the left/right of center won't show up, but you can still swipe through the list.

Jay

@ J. A. Whye - Thanks for the help!

I already tried to set a dynamic mask, so there's no popping-in and out (alpha 1/0) of the rectangle and that actually works. Although I think my code can be optimized and written better.

In my example you'll see that I insert a mask, that should be a 200x200 rectangle, but it shows a 1000x200 rectangle.

Can anybody take a look at it and make suggestions/optimizations?

Here's my example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
local deviceWidth, deviceHeight, widthRatio, heightRatio
 
deviceWidth = display.contentWidth
deviceHeight = display.contentHeight
 
-- Set ratiovalues for procentual calculations
widthRatio = math.floor(deviceWidth/100)
heightRatio = math.floor(deviceHeight/100)
 
-- Set white background
local background = display.newRect(0,0,deviceWidth,deviceHeight)
 
-- SET UP MASK ----------------
local dynamicMask = display.newGroup();
local maskBg = display.newRect(display.screenOriginX,display.screenOriginY,deviceWidth,deviceHeight)
maskBg:setFillColor(255,255,255)
dynamicMask:insert(maskBg);
local maskBoxX = display.contentCenterX
local maskBoxY = display.contentCenterY + (heightRatio*10)
local maskBox = display.newRect(0,0, 200,200)
maskBox.x = 0
maskBox.y = maskBoxY
dynamicMask:insert(maskBox);
maskBox:setFillColor(0,0,0);
display.save (dynamicMask, "tmp.jpg",  system.TemporaryDirectory)
maskBox:removeSelf()
local mask = graphics.newMask( "tmp.jpg", system.TemporaryDirectory )
-- /SET UP MASK ----------------
 
local menus = {}
local num = 7
local xPosHandler = {}
diff = 0
local function handleTouch(e)
        local phase = e.phase
        local t = e.target
        if "began" == phase then
                for i=1,num do
                        xPosHandler[i] = e.x - menus[i].x
                end
                display.getCurrentStage():setFocus(t)
                t.isFocus = true
        elseif "moved" == phase and t.isFocus  then
                for i=1,num do
                        menus[i].x = e.x - xPosHandler[i]
                end
        elseif "ended" == phase then
                display.getCurrentStage():setFocus(nil)
                t.isFocus = false
                for i=1,num do
                       if menus[i].x > 240 - 80 and  menus[i].x < 240 + 80 then
                                diff  = menus[i].x - 240
                       end
                end
                
                for i=1,num do
                        transition.to(menus[i],{x = menus[i].x - diff,time = 500})
                end
                
        end
end
 
for i=1,num do 
        menus[i] = display.newRect(0,0,100,100)
                menus[i]:setFillColor(0,100,100,200)
        menus[i].x = maskBoxX + (i-1) * 150
        menus[i].y = maskBoxY
        menus[i].myName = i
        menus[i]:addEventListener("touch",handleTouch)
end
 
thisMainRect = display.newRect(display.screenOriginX,display.screenOriginY,1280,deviceHeight)
thisMainRect:setFillColor(0,255,255);
thisMainRect:setMask(nil)
thisMainRect:setMask(mask)

An update about setting the alpha -- I actually changed the original code so the alpha is set using a transition.to with a time=200. So the objects quickly fade in and out instead of popping.

Just that little tweak gives the whole thing a more polished feel, I think.

Jay

@timwils :-

can i ask why are you using such hard method why display.save , setMask there is no need of that the js example which you had shown me is very easy and also something similar to example give here you just have to change that example if you are going to use a lot of images else it will be fine with some little modification. like the example i had give with the starting one more, put this line at the end

local rect =display.newRect(0,0,100,320)
rect:setFillColor(0)

local rect1 =display.newRect(380,0,100,320)
rect1:setFillColor(0)

@J. A. Whye (cpm guy)

where you had update sorry i can't find that

:)

@ hgvyas123 - Thanks for the suggestion!

It's indeed probably the best solution to just put 2 rectangles with the same color as the background at the point where I wanted to "mask" them out :-)
I think I will go for this suggestion.

It's als good to know that there's not some simple widget or function to create a viewport from a vectorobject/displayobject where everything placed in that object only shows if they're in the viewport. In html it's easy (example), so I thought that it would be just as easy with Corona :o)

HI
Try to use and modify slideView from sample projects. Works great.

views:1718 update:2011/9/27 18:14:54
corona forums © 2003-2011