Source: Rikulo Blog

Rikulo Blog A Photo Album Prototype with Swipe Gesture

The PlanWe are going to build an album-like demo as an application of the new SwipeGesture. If you are a front end web developer, you should be familiar with the construction:Then we are going to wire up a SwipeGesture and a Motion, so that the pictures will shift when they receive a swipe gesture.The OutcomeSwipe to view next or previous photo.The pictures are distributed under Creative Commons license.Original pictures came from Kim Carpenter, sophie, Kate, Chris. P, Kabacchi.Layout and Responsive DesignWe start by laying down the views:final View frame = new View(); frame.style.overflow = "hidden"; frame.profile.location = "center center"; // frame width/height = minimum of [window width] and [window height] final View frameInner = new View(); // frameInner height = [frame height] // frameInner width = [frame width] * [photo count] // frameInner top = 0 (default) // frameInner left = - [photo index] * [frame width] frame.addChild(frameInner); for (int i = 0; i < photoCount; i++) { View photoBox = new View(); // photoBox width/height = [frame width/height] - 50, capped at 500 // photoBox top = an offset which makes it center-aligned to frame // photoBox left = [the offset] + [photo index] * [frame width/height] Image photo = new Image(); photo.classes.add("photo"); photo.profile.text = "location: top left; width: 100%; height: 100%"; photo.src = "res/alpaca-0${i+1}.jpg"; View mask = new View(); // to block browser's default image dragging mask.classes.add("photo-mask"); mask.profile.text = "location: top left; width: 100%; height: 100%"; photoBox.addChild(photo); photoBox.addChild(mask); frameInner.addChild(photoBox); } mainView.addChild(frame); Note that the size settings of some views are purposely left out, as we are going to handle it directly within the layout callback, so they will be responsive automatically:frame.on.preLayout.add((LayoutEvent event) { final Size msize = new DOMQuery(mainView).innerSize; frameSize = min(msize.width, msize.height); final int photoSize = min(frameSize - 50, 500); final int photoOffset = ((frameSize - photoSize) / 2).toInt(); frame.width = frame.height = frameInner.height = frameSize; frameInner.width = frameSize * photoCount; frameInner.left = -_index * frameSize; for (int i = 0; i < photoCount; i++) { View photoBox = frameInner.children[i]; photoBox.width = photoBox.height = photoSize; photoBox.left = photoOffset + i * frameSize; photoBox.top = photoOffset; } }); Business LogicNow we are going to write down the business logic:int _index = 0; void next() => select(_index + 1); void previous() => select(_index - 1); void select(int index) { if (index < 0 || index >= photoCount) { // do nothing return; } // TODO: trigger an animation to shift the photos } AnimationThe animation part is straightforward:void select(int index) { if (index < 0 || index >= photoCount) { // do nothing return; } // trigger an animation to shift the photos final Offset origin = new Offset(-_index * frameSize, 0); final Offset dest = new Offset(-index * frameSize, 0); new LinearPathMotion(frameInner.node, origin, dest, end: (MotionState state) { _index = index; }, easing: (num x) => x * x); } Swipe GestureHere we are going to capture user's swipe gesture.new SwipeGesture(mainView.node, (SwipeGestureState state) { final int diff = state.delta.x; if (diff < -50) // swipe left next(); else if (diff > 50) // swipe right previous(); }); But wait! There is an issue with this implementation. Whenever there are multiple gestures/motions in the game, it is necessary to consider whether they will conflict each other. Generally there will be a priority, where one gesture/motion will block or interrupt another.In the previous example we have shown how a gesture interrupts a motion. In this scenario, we are going to make the photo-shifting motion block the incoming swipe gesture:SwipeGesture gesture; gesture = new SwipeGesture(mainView.node, (SwipeGestureState state) { gesture.disable(); final int diff = state.delta.x; if (diff < -50) // swipe left next(); else if (diff > 50) // swipe right previous(); else gesture.enable(); }); void select(int index) { if (index < 0 || index >= photoCount) { gesture.enable(); return; } final Offset origin = new Offset(-_index * frameSize, 0); final Offset dest = new Offset(-index * frameSize, 0); new LinearPathMotion(frameInner.node, origin, dest, end: (MotionState state) { _index = index; gesture.enable(); }, easing: (num x) => x * x); } The gestures come with enable/disable APIs, allowing us to easily turn it on and off.ConclusionAt the end we added a few more decorations to the demo to make it fancier. They are quite straightforward to figure out from the source code.

Read full article »
Est. Annual Revenue
$100K-5.0M
Est. Employees
1-25
CEO Avatar

CEO

Update CEO

CEO Approval Rating

- -/100



Rikulo is a Private company. Rikulo has a revenue of $1M, and 10 employees. Rikulo has 2 followers on Owler.