Move to peek - Like Facebook paper app
It is interesting to note the amount of amazing effects added into Facebook paper app. In the next few tutorials, while we shall recreate these effects which are useful for medium to advance level developers, Beginners can read and understand the underlying principles which make learning a bit more interesting (visually atelast)
The Effect
The effect that we are trying to replicate is moving the current view and displaying the view underneath which fades in slowly based on how much have we pulled the upper layer to peek underneath. The same in video form.The Theory
The upper layer is moveable and can be slid vertically. As it is moved up, it uncovers the previous view underneath. Instead of simply displaying it uncovered, we fade the same from black. It is visible the more we pull the upper layer off. If we let go, the upper layer animated back to cover it and if we have pulled the upper layer to the threshold, it is peeled off displaying the layer underneath.Technical Note
For the purpose of this demo, we are using images to represent the two layers, if it were in an app, you would have had UIViews (iOS). Even if you were trying this with Lua, you would have to create two layers / groups.Creating the layers
For recreating this effect, we shall have three layers, the front, the bottom and the shroud. The placement is the bottom layer, then the shroud and then finally the front. The shroud is a big black 'Shroud' that obscures the bottom view. We change the opacity of this layer to show / hide the bottom layer based on how much the front layer has been moved.local bottom = Bitmap.new(Texture.new("image1.jpg")) stage:addChild(bottom) local shroud = rectangle(0, 0, _W, _H, 0x000000) stage:addChild(shroud) local front = Bitmap.new(Texture.new("image2.jpg")) stage:addChild(front)
Note
We have created a function called rectangle that takes five parameters, the x, y, width, height and the color. This creates a shape object with a black rectangle. This function is defined asfunction rectangle(x, y, width, height, color) local sh = Shape.new() sh:clear() sh:setLineStyle(0,0x00,0) sh:setFillStyle(Shae.SOLID, 0x00, 1) sh:beginPath() sh:moveTo(0,0) sh:lineTo(_W, 0) sh:lineTo(_W, _H) sh:lineTo(0, _H) sh:lineTo(0,0) sh:closePath() sh:endPath() sh:setPosition(x, y) return sh end
Setting up
We would also need a couple of other variables that will help us work with the demo code, this will be at the top of your main.lua before we create the layers. The initialization code islocal animate = false local speed = 0.2 local _W = application:getDeviceWidth() local _H = application:getDeviceHeight()
Moving the top layer
Now we can see the top layer covering up both the shroud and the bottom layer, we want this to be moveable. So to do so, we need to attach a handler that will handle the touch events. We need to have three handlers, for each of the three stages of touch, the TOUCH_BEGIN when the finger touches the screen, the TOUCH_MOVE when the finger still touching the screen is moved and the TOUCH_END when the finger is released off the screen. We add the listeners to the front layer as followsfront:addEventListener(Event.TOUCHES_BEGIN, front.onDown, front) front:addEventListener(Event.TOUCHES_MOVE, front.onMove, front) front:addEventListener(Event.TOUCHES_END, front.onUp, front)and we need to add these functions or we would get an error that these functions do not exist.
TOUCHES_BEGIN
A small note about handling touches, you might feel that much of the code is redundant, however it helps to create good habits, not saying that this is the best way.function front:onDown(e) self.focus = true self.sy = e.touch.y or 0 endyou might have noticed that the function is not simply called
onDown
, but instead front:onDown(e)
, which is the other way of saying front.onDown(self,e)
and therefore in the addEventListener we are using front.onDown not just onDown. We first create a new property called focus and set it to true, this is useful as we can check if the touch did originate on this object or not, because in the onMove, when we start to move the layer, what if we had never started our touch on this object, we would be moving this layer like a ghost layer. However in our case the layer is full screen so we could not have not initiated our touch anywhere other than on the layer. Next we set another property called sy (or as refer to it in my mind as the start y) this is the point where the touch started. It is handy to know this to be able to move the image in reference to this point. You will see what I mean, set this value as 0 instead of e.touch.y and see how it goes. TOUCHES_MOVE
This is where the bulk of our code lies. First we check if we have the focus (touch started on this object) otherwise return. Next we calculate the amount the touch has moved from the last time and then add that delta (differential) to the current position of the front image.function front:onMove(e) if self.focus ~= true then return end local dy = e.touch.y - self.sy local y = self:getY() self:setY( y + dy ) self.sy = e.touch.y endNow you will see that you can move the image both ways, peek up or peek down, we want this moving only in one direction not both, so we ignore if the layer is moved downwards to peek.
if self:getY() > 0 then self:setY(0) endjust that one line added to the function above only allows us to move the layer upwards to uncover and pull it back to cover, but not pull it down.
Adding the fade
This is rather simple, we simply need to set the alpha property for the shroud depending on the distance the front layer has been moved, we use a bit of math for that aslocal alpha = (math.abs(self:getY()) / _H * 0.75) shroud:setAlpha ( 1 - al )
TOUCHES_END
This is the last event handler that we work with and this resets the movement or changes the layer as required.function front:onUp(e) self.focus = nil local y = math.abs(self:getY()) if y > _H/1.5 then self:setY(-_H) shroud:setAlpha(0) else self:setY(0) shroud:setAlpha(1) end endWell, that's all there is to creating that effect. It really is that simple
Comments
Post a Comment