Stepped scroll view

I’m trying to implement a scrollview which will snap to given positions within the scroll distance. Does anyone have code to do this, please?

What I’m looking for is something similar to the iOS photo viewer. The specific behaviour appears to allow scrolling while the touch is held and when it is released the view continues to scroll until the friction drops it below a threshold velocity. At that point the view is transitioned to it’s nearest snapping point.

This is what I’ve implemented below, though it is rather rough:

 local scrollView local previousPos = 0 local function enterFrame() local currentPos = scrollView:getContentPosition() local speed = math.abs( currentPos - previousPos ) previousPos = currentPos if (speed \< 4) then local x = math.round( currentPos / display.actualContentWidth ) scrollView:scrollToPosition{ x=x\*display.actualContentWidth } Runtime:removeEventListener( "enterFrame", enterFrame ) end end local function scrollListener( event ) local phase = event.phase if ( phase == "began" ) then --print( "Scroll view was touched" ) elseif ( phase == "moved" ) then --print( "Scroll view was moved" ) elseif ( phase == "ended" ) then --print( "Scroll view was released" ) Runtime:addEventListener( "enterFrame", enterFrame ) end return true end scrollView = widget.newScrollView { top = 0, left = 0, width = display.actualContentWidth, height = display.actualContentHeight, scrollWidth = display.actualContentWidth\*10, scrollHeight = 0, verticalScrollDisabled = true, backgroundColor = {1,0,0,.1}, friction = .3, listener = scrollListener, }

Well, a slight improvement here. Still not convinced it’s the same effect seen in the Photos app though…

 local scrollView local function enterFrame() if (scrollView.\_view.\_velocity \< 2) then local x = math.round( scrollView:getContentPosition() / display.actualContentWidth ) scrollView:scrollToPosition{ x=x\*display.actualContentWidth } Runtime:removeEventListener( "enterFrame", enterFrame ) end end local function scrollListener( event ) if (not event.limitReached and event.phase == "ended") then --print( "Scroll view was released" ) Runtime:addEventListener( "enterFrame", enterFrame ) end return true end scrollView = widget.newScrollView { top = display.actualContentHeight\*.2, left = 0, width = display.actualContentWidth, height = display.actualContentHeight\*.8, scrollWidth = display.actualContentWidth\*6, scrollHeight = 0, verticalScrollDisabled = true, backgroundColor = {1,0,0,.1}, friction = .3, listener = scrollListener, } scrollView.\_view.\_trackVelocity = true

Well, a slight improvement here. Still not convinced it’s the same effect seen in the Photos app though…

 local scrollView local function enterFrame() if (scrollView.\_view.\_velocity \< 2) then local x = math.round( scrollView:getContentPosition() / display.actualContentWidth ) scrollView:scrollToPosition{ x=x\*display.actualContentWidth } Runtime:removeEventListener( "enterFrame", enterFrame ) end end local function scrollListener( event ) if (not event.limitReached and event.phase == "ended") then --print( "Scroll view was released" ) Runtime:addEventListener( "enterFrame", enterFrame ) end return true end scrollView = widget.newScrollView { top = display.actualContentHeight\*.2, left = 0, width = display.actualContentWidth, height = display.actualContentHeight\*.8, scrollWidth = display.actualContentWidth\*6, scrollHeight = 0, verticalScrollDisabled = true, backgroundColor = {1,0,0,.1}, friction = .3, listener = scrollListener, } scrollView.\_view.\_trackVelocity = true