Cycling through a list of objects with arrow buttons

So what I am trying to achieve is where I have 2 arrows and I have a set of images and you can use the arrows to go through the images (forwards and backwards). Each image also then would have an event listener so that if touched it would go to a new scene.

I imagine the way to do it is to put them in a table of some sort and just have the arrows go up or down through the list?

How would I set this up and how do you add properties like the touch event to items that would be in a list?

Thanks in advance for any help

Hi …

i am sure there are many ways to do it …but i made this one for you… it might not optimal but at least you can start with it .

[lua]

local widget = require( “widget” )

myImages = {“image1.jpg”, “image2.jpg”, “image3.jpg” }  – name of images

currentImageIndex = 1  – this is index to track your current image

– display the first image

myCurrentImage = display.newImage( myImages[1])

myCurrentImage.x = 150

myCurrentImage.y = 100

– Function to handle back and forward buttons

local function handleButtonEvent( event )

    if ( “ended” == event.phase ) then

        if event.target.id == “back” and currentImageIndex > 1  then

          print( “Back” )

          myCurrentImage:removeSelf()

          myCurrentImage = nil

          myCurrentImage = display.newImage( myImages[currentImageIndex - 1])

          myCurrentImage.x = 150

          myCurrentImage.y = 100

          currentImageIndex = currentImageIndex - 1

        elseif event.target.id == “fwd” and currentImageIndex < 3 then

        print( “fwd” )

          myCurrentImage:removeSelf()

          myCurrentImage = nil

          myCurrentImage = display.newImage( myImages[currentImageIndex + 1])

          myCurrentImage.x = 150

          myCurrentImage.y = 100

          currentImageIndex = currentImageIndex + 1

        end

    end

end

local back = widget.newButton

{

    left = 0,

    top = 200,

    id = “back”,

    label = “Go Back”,

    onEvent = handleButtonEvent

}

local fwd = widget.newButton

{

    left = 120,

    top = 200,

    id = “fwd”,

    label = “Go to forword”,

    onEvent = handleButtonEvent

}

[/lua]

A rough draft to get you started:

local items = {} local numItems = 5 local xIncrement = 0 local itemSeparation = 50 local itemGroup = display.newGroup() local function itemTap(event) -- do stuff end for i = 1, numItems do items[i] = display.newImageRect("crate.png", 40, 40) items[i].x = display.contentCenterX + xIncrement xIncrement = xIncrement + itemSeparation items[i].y = display.contentCenterY items[i]:addEventListener("tap", itemTap) itemGroup:insert(items[i]) end local leftButton = display.newImageRect("crate.png", 50, 50) leftButton.x, leftButton.y = 50, 350 local rightButton = display.newImageRect("crate.png", 50, 50) rightButton.x, rightButton.y = 270, 350 local function tapHandler(event) if event.target == leftButton then transition.to( itemGroup, { time = 500, x = itemGroup.x - itemSeparation } ) elseif event.target == rightButton then transition.to( itemGroup, { time = 500, x = itemGroup.x + itemSeparation } ) end end leftButton:addEventListener("tap", tapHandler) rightButton:addEventListener("tap", tapHandler)

Of course, if you’re working with composer or storyboard, you’ll have more to do to get it to work, but it might answer some of your questions.

Guys thanks so much for your replies - both look like they will help me a lot.

@Alzaabi98 - that looks like exactly what I want, or at least most of the way there. Really appreciate your help!

I am using composer but I figure once I add everything to the group there shouldnt be any big issues?

Alzaabi - the code works great thanks. I just need to add in that you can click on the images and call the scene to go to and that will be it perfect.

One small issue I am having though.

I have an image thats the width of the screen in the table. Then on top of that I have the 2 arrows - left and right.

When I use the arrow to move to the next item in the table, that item gets drawn but its drawn over the arrows.

I tried to use :toFront() on the arrows after the image gets drawn in the handleEventFunction but because they are created further down they cant be seen by the function. Any suggestions?

You can just forward declare them. Remove the locals in front of fwd and back and then somewhere up the top you can just put

local fwd, back

This will reserve a space for them in memory, so even though they are nil when you first create the handleButtonEvent function, this function will know where they’re going to be - and you’ll have them “filled in” so-to-speak by the time they’re used.

An upgade to Alzaabi’s code, to fully cycle between images (pressing forwared in the last one will go to the first one, and viceversa) and showing the current image / last image of the table as well:

local widget = require( "widget" ) local myImages = {"image1.png", "image2.png", "image3.png" } -- name of images local buttons = {back,fwd} local index = 1 -- this is index to track your current image -- display the first image local myCurrentImage = display.newImage( myImages[1]) myCurrentImage.x = 150 myCurrentImage.y = 100 local indexText = display.newText(index.."/"..#myImages,400,150,nil,50) -- Function to handle back and forward buttons local function handleButtonEvent( event ) if ( "ended" == event.phase ) then if event.target.id == "back" then if index \> 1 then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[index - 1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = index - 1 indexText.text = index.."/"..#myImages elseif index == 1 then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[#myImages]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = #myImages indexText.text = index.."/"..#myImages end elseif event.target.id == "fwd" then if index \< #myImages then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[index + 1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = index + 1 indexText.text = index.."/"..#myImages elseif index == #myImages then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = 1 indexText.text = index.."/"..#myImages end end end end buttons.back = widget.newButton { left = 0, top = 200, id = "back", label = "Go Back", onEvent = handleButtonEvent } buttons.fwd = widget.newButton { left = 120, top = 200, id = "fwd", label = "Go forward", onEvent = handleButtonEvent }

Hi guys,

On the above piece - it seems that when the images are placed initially it sees them both as the standard version and the @2 version. However when I scroll through them it seems that the @2x version doesnt get recognised once the update happens when using the arrows. Any ideas why this is?

Edit -sorry posted from old account (CrazyApeStudios here)

Hi @alan73,

I suppose you’re referring to the code in the “Best Answer” post? If so, that code does not use “display.newImageRect()” to display the images, but rather “display.newImage()”. So, it won’t ever select the dynamically-chosen image like normal, @2x, @4x, etc. Of course, it would be pretty simple to adjust the code for that, but you’ll need to do handle that yourself and pass the proper image width/height to “display.newImageRect()”.

Best regards,

Brent

Hi …

i am sure there are many ways to do it …but i made this one for you… it might not optimal but at least you can start with it .

[lua]

local widget = require( “widget” )

myImages = {“image1.jpg”, “image2.jpg”, “image3.jpg” }  – name of images

currentImageIndex = 1  – this is index to track your current image

– display the first image

myCurrentImage = display.newImage( myImages[1])

myCurrentImage.x = 150

myCurrentImage.y = 100

– Function to handle back and forward buttons

local function handleButtonEvent( event )

    if ( “ended” == event.phase ) then

        if event.target.id == “back” and currentImageIndex > 1  then

          print( “Back” )

          myCurrentImage:removeSelf()

          myCurrentImage = nil

          myCurrentImage = display.newImage( myImages[currentImageIndex - 1])

          myCurrentImage.x = 150

          myCurrentImage.y = 100

          currentImageIndex = currentImageIndex - 1

        elseif event.target.id == “fwd” and currentImageIndex < 3 then

        print( “fwd” )

          myCurrentImage:removeSelf()

          myCurrentImage = nil

          myCurrentImage = display.newImage( myImages[currentImageIndex + 1])

          myCurrentImage.x = 150

          myCurrentImage.y = 100

          currentImageIndex = currentImageIndex + 1

        end

    end

end

local back = widget.newButton

{

    left = 0,

    top = 200,

    id = “back”,

    label = “Go Back”,

    onEvent = handleButtonEvent

}

local fwd = widget.newButton

{

    left = 120,

    top = 200,

    id = “fwd”,

    label = “Go to forword”,

    onEvent = handleButtonEvent

}

[/lua]

A rough draft to get you started:

local items = {} local numItems = 5 local xIncrement = 0 local itemSeparation = 50 local itemGroup = display.newGroup() local function itemTap(event) -- do stuff end for i = 1, numItems do items[i] = display.newImageRect("crate.png", 40, 40) items[i].x = display.contentCenterX + xIncrement xIncrement = xIncrement + itemSeparation items[i].y = display.contentCenterY items[i]:addEventListener("tap", itemTap) itemGroup:insert(items[i]) end local leftButton = display.newImageRect("crate.png", 50, 50) leftButton.x, leftButton.y = 50, 350 local rightButton = display.newImageRect("crate.png", 50, 50) rightButton.x, rightButton.y = 270, 350 local function tapHandler(event) if event.target == leftButton then transition.to( itemGroup, { time = 500, x = itemGroup.x - itemSeparation } ) elseif event.target == rightButton then transition.to( itemGroup, { time = 500, x = itemGroup.x + itemSeparation } ) end end leftButton:addEventListener("tap", tapHandler) rightButton:addEventListener("tap", tapHandler)

Of course, if you’re working with composer or storyboard, you’ll have more to do to get it to work, but it might answer some of your questions.

Guys thanks so much for your replies - both look like they will help me a lot.

@Alzaabi98 - that looks like exactly what I want, or at least most of the way there. Really appreciate your help!

I am using composer but I figure once I add everything to the group there shouldnt be any big issues?

Alzaabi - the code works great thanks. I just need to add in that you can click on the images and call the scene to go to and that will be it perfect.

One small issue I am having though.

I have an image thats the width of the screen in the table. Then on top of that I have the 2 arrows - left and right.

When I use the arrow to move to the next item in the table, that item gets drawn but its drawn over the arrows.

I tried to use :toFront() on the arrows after the image gets drawn in the handleEventFunction but because they are created further down they cant be seen by the function. Any suggestions?

You can just forward declare them. Remove the locals in front of fwd and back and then somewhere up the top you can just put

local fwd, back

This will reserve a space for them in memory, so even though they are nil when you first create the handleButtonEvent function, this function will know where they’re going to be - and you’ll have them “filled in” so-to-speak by the time they’re used.

An upgade to Alzaabi’s code, to fully cycle between images (pressing forwared in the last one will go to the first one, and viceversa) and showing the current image / last image of the table as well:

local widget = require( "widget" ) local myImages = {"image1.png", "image2.png", "image3.png" } -- name of images local buttons = {back,fwd} local index = 1 -- this is index to track your current image -- display the first image local myCurrentImage = display.newImage( myImages[1]) myCurrentImage.x = 150 myCurrentImage.y = 100 local indexText = display.newText(index.."/"..#myImages,400,150,nil,50) -- Function to handle back and forward buttons local function handleButtonEvent( event ) if ( "ended" == event.phase ) then if event.target.id == "back" then if index \> 1 then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[index - 1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = index - 1 indexText.text = index.."/"..#myImages elseif index == 1 then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[#myImages]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = #myImages indexText.text = index.."/"..#myImages end elseif event.target.id == "fwd" then if index \< #myImages then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[index + 1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = index + 1 indexText.text = index.."/"..#myImages elseif index == #myImages then myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[1]) myCurrentImage.x = 150 myCurrentImage.y = 100 index = 1 indexText.text = index.."/"..#myImages end end end end buttons.back = widget.newButton { left = 0, top = 200, id = "back", label = "Go Back", onEvent = handleButtonEvent } buttons.fwd = widget.newButton { left = 120, top = 200, id = "fwd", label = "Go forward", onEvent = handleButtonEvent }

Hi guys,

On the above piece - it seems that when the images are placed initially it sees them both as the standard version and the @2 version. However when I scroll through them it seems that the @2x version doesnt get recognised once the update happens when using the arrows. Any ideas why this is?

Edit -sorry posted from old account (CrazyApeStudios here)

Hi @alan73,

I suppose you’re referring to the code in the “Best Answer” post? If so, that code does not use “display.newImageRect()” to display the images, but rather “display.newImage()”. So, it won’t ever select the dynamically-chosen image like normal, @2x, @4x, etc. Of course, it would be pretty simple to adjust the code for that, but you’ll need to do handle that yourself and pass the proper image width/height to “display.newImageRect()”.

Best regards,

Brent