Created
December 30, 2016 14:48
-
-
Save HoraceBury/eeab199c040673f04d391ae744ee2ea3 to your computer and use it in GitHub Desktop.
Provides a scrollview widget which can have items dragged off it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local widget = require("widget") | |
local function angleOf( ax, ay, bx, by, adjust, positive ) | |
local angle = math.atan2( by-ay, bx-ax ) * 180/math.pi | |
if (adjust) then | |
if (type(adjust) ~= "number") then adjust = -90 end | |
angle = angle - adjust | |
if (angle < -180) then angle=angle+360 end | |
if (angle > 180) then angle=angle-360 end | |
end | |
if (positive) then | |
if (angle < 0) then | |
angle = angle + 360 | |
elseif (angle > 360) then | |
angle = angle - 360 | |
end | |
end | |
return angle | |
end | |
local function lengthOf( ax, ay, bx, by ) | |
local width, height = bx-ax, by-ay | |
return (width*width + height*height) ^ 0.5 -- math.sqrt(width*width + height*height) | |
end | |
function widget.newDragItemsScrollView( params ) | |
local scrollview = widget.newScrollView( params ) | |
function scrollview:add( item, listener, dragtime, angle, radius, touchthreshold ) | |
scrollview:insert( item ) | |
local dragtimer = nil | |
local touchevent = nil | |
local touch = nil | |
touchthreshold = touchthreshold or display.actualContentWidth*.1 | |
local function isWithinRadius(e) | |
local angle = angleOf( e.xStart, e.yStart, e.x, e.y, angle-90, false ) | |
return (angle > -radius/2 and angle < radius/2) | |
end | |
local function cancelDragTimer() | |
if (dragtimer) then | |
timer.cancel( dragtimer ) | |
dragtimer = nil | |
end | |
end | |
local function startDragByHold() | |
print("start by hold") | |
item:removeEventListener( "touch", touch ) | |
listener( item, touchevent ) | |
item, touchevent = nil, nil | |
end | |
local function startDragByTouch() | |
print("start by drag") | |
cancelDragTimer() | |
item:removeEventListener( "touch", touch ) | |
listener( item, touchevent ) | |
item, touchevent = nil, nil | |
end | |
touch = function( event ) | |
touchevent = event | |
if (event.phase == "began") then | |
display.currentStage:setFocus( event.target, event.id ) | |
event.target.hasFocus = true | |
if (dragtime) then | |
dragtimer = timer.performWithDelay( dragtime, startDragByHold, 1 ) | |
end | |
return true | |
elseif (event.target.hasFocus) then | |
if (event.phase == "moved") then | |
if (lengthOf( event.xStart, event.yStart, event.x, event.y ) > touchthreshold) then | |
cancelDragTimer() | |
if (angle and radius and isWithinRadius(event)) then | |
startDragByTouch() | |
else | |
scrollview:takeFocus(event) | |
return false | |
end | |
end | |
else | |
display.currentStage:setFocus( event.target, nil ) | |
event.target.hasFocus = nil | |
end | |
return true | |
end | |
return false | |
end | |
item:addEventListener( "touch", touch ) | |
end | |
return scrollview | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- attach drag-item scrollview to widget library | |
require("dragitemscrollview") | |
-- load widget library | |
local widget = require("widget") | |
-- create drag-item scrollview | |
local c = widget.newDragItemsScrollView{ | |
backgroundColor = {1,0,0}, | |
left=100, | |
top=100, | |
width=500, | |
height=800 | |
} | |
-- create item to add to the scroll view (this will be dragged off the scrollview) | |
local circle = display.newCircle( 0, 0, 50 ) | |
-- create a listener to handle drag-item events | |
local function listen( item, touchevent ) | |
display.currentStage:insert( item ) | |
item.x, item.y = touchevent.x, touchevent.y | |
local function touch(e) | |
if (e.phase == "began") then | |
display.currentStage:setFocus( e.target, e.id ) | |
e.target.hasFocus = true | |
return true | |
elseif (e.target.hasFocus) then | |
e.target.x, e.target.y = e.x, e.y | |
if (e.phase == "moved") then | |
else | |
display.currentStage:setFocus( e.target, nil ) | |
e.target.hasFocus = nil | |
end | |
return true | |
end | |
return false | |
end | |
item.hasFocus = true | |
display.currentStage:setFocus( item, touchevent.id ) | |
item:addEventListener( "touch", touch ) | |
end | |
-- add the drag-item to the scrollview | |
--[[ | |
Params: | |
item: Item to add to the scrollview | |
listener: Listener function to call when a drag-off is detected | |
Dragtime: Milliseconds that a hold will begin a drag-off | |
Angle: Angle at which a touch-motion will begin a drag-off event | |
Radius: Radius around the angle within which the drag-off will begin, outside this will not | |
Touch-threshold: Distance a touch must travel to begin a drag-off (default is .1 of screen width) | |
Description: | |
This example will cause the white circle to be dragged off the scrollview only if the | |
touch begins and does not move further than the touch-threshold within 450 milliseconds | |
OR if the touch moves further than .1 of the screen width within 450 millisecond | |
BUT ONLY if the touch moves within 90 degrees of immediately east (right) of the initial touch. | |
The Dragtime determines how long a touch-and-hold will cause a drag to fire. Leave nil to | |
have only touch with distance begin a drag-off. | |
Angle and Radius define a range of direction which will fire a drag-off event. Outside of that | |
will result in the scrollview being scrolled. Leave nil to have only touch-and-hold to fire a | |
drag-off event. | |
The Touch-threshold can be used to define the distance that a touch-and-move will fire a | |
drag-off event. The default is .1 of the screen width. | |
]]-- | |
c:add( circle, listen, 450, 90, 90 ) | |
-- position the drag item in the scrollview | |
circle.x, circle.y = c.width/2, c.height/5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment