Skip to content

Instantly share code, notes, and snippets.

@rannerboy
Last active April 22, 2020 13:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rannerboy/e84a75d7e17265d077a0b72a039209c1 to your computer and use it in GitHub Desktop.
Save rannerboy/e84a75d7e17265d077a0b72a039209c1 to your computer and use it in GitHub Desktop.
Corona SDK slideshow module - Swiping objects left and right
--[[
Example of using the slideshow module
Creates a number of large circles as the main display groups used by the slideshow example
Also creates thumbnails that will be updated by callbacks from the slidehow module
Markus Ranner 2016
--]]
local slideshow = require("slideshow")
display.setStatusBar(display.HiddenStatusBar)
--[[
Create circles of random colors to use as slideshow objects
--]]
local function createSlideshowObjects(numberOfObjects)
local objects = {}
for i = 1, numberOfObjects do
--[[
Each slideshow object is added to its own display group.
This is not really necessary in this example, but shows that the slideshow works with display groups which will be the most likely use case
--]]
local group = display.newGroup()
local circle = display.newCircle(0, 0, 200)
-- Save the fill color as a property to be able to retrieve it later for the thumbnails
circle.fillColor = { math.random(), math.random(), math.random(), 1 }
circle:setFillColor(unpack(circle.fillColor))
group:insert(circle)
objects[#objects + 1] = group
end
return objects
end
--[[
Create and return a display group containing a thumbnail for each of the slideshow objects
--]]
function createThumbnails(slideshowObjects)
local group = display.newGroup()
local thumbSize = 30
local thumbMargin = 10
for i = 1, #slideshowObjects do
-- Since we added the slideshow objects to a display group, we get the first (only) object of the group here to find out its color
local obj = slideshowObjects[i][1]
local thumb = display.newCircle((i - 1) * (thumbSize + thumbMargin), 0, thumbSize / 2, thumbSize / 2)
thumb:setFillColor(unpack(obj.fillColor))
thumb:setStrokeColor(1, 1, 1, 1.0)
thumb.strokeWidth = 0
thumb.anchorX = 0
-- Setup a tap handler for each thumb that will quick jump to selected object index
thumb:addEventListener("tap", function()
local disableTransition = false
slideshow.showObjectAtIndex(i, disableTransition)
end)
group:insert(thumb)
end
group.x = display.contentCenterX - (#slideshowObjects / 2 * (thumbSize + thumbMargin))
group.y = display.contentHeight - 100
return group
end
math.randomseed( os.time() )
-- Setup the objects and thumbnails to use for the slideshow
local slideshowObjects = createSlideshowObjects(9)
local thumbnailsGroup = createThumbnails(slideshowObjects)
local function updateThumbnails(selectedObjectIndex)
-- Highlight the stroke of the selected object's corresponding thumbnail
for i = 1, thumbnailsGroup.numChildren do
local thumb = thumbnailsGroup[i]
if (i == selectedObjectIndex) then
thumb.strokeWidth = 3
else
thumb.strokeWidth = 0
end
end
end
--[[
Start the slideshow
This example shows all the customizable parameters, but all the parameters are optional
--]]
local slideshowParams = {
startIndex = 5,
transitionEffect = easing.outCubic,
transitionEffectTimeMs = 250,
y = display.contentCenterY - 100,
swipeSensitivityPixels = 50,
onChange = updateThumbnails,
}
slideshow.init(slideshowObjects, slideshowParams)
--[[
Corona SDK slideshow module
Handles a number of display objects/groups, displaying only one at a time.
Allows user to swipe left/right to change displayed object.
Uses callbacks to update other parts of the program when a new object is displayed.
Markus Ranner 2016
--]]
-- State
local _slideshowObjects
local _currentObjectIndex
local _transitionEffectTimeMs
local _transitionEffect
local _swipeSensitivityPixels
local _onChange
local function showObject(objectIndex, disableTransition)
local objectToShow = _slideshowObjects[objectIndex]
-- Update current object index and make a callback if selected object has changed
if(_currentObjectIndex ~= objectIndex) then
_currentObjectIndex = objectIndex
if (_onChange) then
_onChange(_currentObjectIndex)
end
end
-- Transition all slideshow objects into place
for i = 1, #_slideshowObjects do
local object = _slideshowObjects[i]
local x = _slideshowObjects[i].originalPosition.x - ((objectIndex - 1) * display.contentWidth)
-- If transition has been disabled, update position immediately
if (disableTransition) then
object.x = x
else
transition.to(object, {
x = x,
time = _transitionEffectTimeMs,
transition = _transitionEffect,
})
end
end
end
local function handleSwipe( event )
local swipedObject = event.target
local swipeDistanceX = event.x - event.xStart
if (event.phase == "began") then
-- Set a focus flag on the object, so that we don't handle touch events that weren't started on the same object
swipedObject.hasFocus = true
-- This redirects all futre touch events to the swiped object, even when touch moves outside of its bounds
display.getCurrentStage():setFocus( swipedObject )
elseif ( event.phase == "moved" ) then
if (swipedObject.hasFocus) then
-- Move all objects according to swipe gesture
for i = 1, #_slideshowObjects do
local object = _slideshowObjects[i]
local offsetX = -((_currentObjectIndex - 1) * display.contentWidth)
local x = object.originalPosition.x + offsetX + swipeDistanceX
object.x = x
end
end
elseif( event.phase == "ended" ) then
-- Reset touch event focus
swipedObject.hasFocus = false
display.getCurrentStage():setFocus( nil )
-- Calculate which object to show next, preventing swiping too far left or right
local nextObjectIndex = _currentObjectIndex
if((swipeDistanceX >= _swipeSensitivityPixels) and (_currentObjectIndex > 1)) then
nextObjectIndex = _currentObjectIndex - 1
elseif((swipeDistanceX <= -_swipeSensitivityPixels) and (_currentObjectIndex < #_slideshowObjects)) then
nextObjectIndex = _currentObjectIndex + 1
end
-- Finally, show the selected object in the slideshow
showObject(nextObjectIndex)
elseif( event.phase == "cancelled" ) then
-- Reset touch event focus
swipedObject.hasFocus = false
display.getCurrentStage():setFocus( nil )
end
return true
end
local function showObjectAtIndex(objectIndex, disableTransition)
showObject(objectIndex, disableTransition)
end
local function init( slideshowObjects, params )
if (not params) then
params = {}
end
-- Set initial state for slideshow component
_transitionEffect = params.transitionEffect or easing.outCirc
_transitionEffectTimeMs = params.transitionEffectTimeMs or 200
_slideshowObjects = slideshowObjects
_swipeSensitivityPixels = params.swipeSensitivityPixels or 100
_onChange = params.onChange or nil
local y = params.y or display.contentCenterY
-- Position each slideshow object and setup a touch handler for each one
for i = 1, #slideshowObjects do
local obj = slideshowObjects[i]
-- Set initial position for every slideshow object
obj.x = display.contentCenterX + ((i - 1) * display.contentWidth)
obj.y = y
-- For display groups, we need to set the anchorChildren property to true to correctly position the child objects
obj.anchorChildren = true
-- The originalPosition will be used to position all slideshow objects correctly while swiping
obj.originalPosition = { x = obj.x , y = obj.y }
obj:addEventListener( "touch", handleSwipe )
end
-- Show selected start object
local startIndex = params.startIndex or 1
local disableTransition = true
showObject(startIndex, disableTransition)
end
local function cleanUp()
_slideshowObjects = nil
_currentObjectIndex = nil
end
return {
init = init,
cleanUp = cleanUp,
showObjectAtIndex = showObjectAtIndex,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment