Card interfaces can be used for a lot more than simply making cool dating apps. Let’s learn how to build them by creating a food matchmaker. Imagine if a child could pre-order his or her lunch from Mom and Dad in the morning by swiping left on the broccoli, and swiping right on the PBJ. Or, in this case, by selecting exactly which desserts you want after dinner, always a critical moment of choice.
To begin with, I scaffolded a basic app using Angular and NativeScript. Since this is a dessert-matchmaking app, in my service, I created a basic array of emoji. Each emoji is placed on a colored card.import { Injectable } from
"@angular/core"
;
import { Emoji } from
"./emoji"
;
@Injectable()
export class CardService {
private emoji =
new
Array<Emoji>(
{ code:
'🍮'
, color:
'b1'
},
{ code:
'🍡'
, color:
'b2'
},
{ code:
'🍨'
, color:
'b3'
},
{ code:
'🍩'
, color:
'b4'
},
{ code:
'🍪'
, color:
'b5'
},
{ code:
'🍰'
, color:
'b5'
},
{ code:
'🍬'
, color:
'b1'
},
{ code:
'🍭'
, color:
'b2'
},
{ code:
'🎂'
, color:
'b3'
},
{ code:
'🍧'
, color:
'b4'
},
{ code:
'🍫'
, color:
'b5'
},
{ code:
'🍦'
, color:
'b6'
}
);
getEmoji(): Emoji[] {
return
this
.emoji;
}
}
.b
1
{
background-color
:
#FFCCDA
;
}
.b
2
{
background-color
:
#FAEEC3
;
}
.b
3
{
background-color
:
#F67982
;
}
.b
4
{
background-color
:
#FFA1A1
;
}
.b
5
{
background-color
:
#FACBAA
;
}
.b
6
{
background-color
:
#F67982
;
}
<
StackLayout
>
<
AbsoluteLayout
horizontalAlignment
=
"center"
paddingTop
=
"30"
#absolutelayout>
<
GridLayout
width
=
"100%"
style
=
"z-index:1"
columns
=
"*,*"
horizontalAlignment
=
"center"
>
<
Label
#no
col
=
"0"
verticalAlignment
=
"center"
text
=
"no, thanks!"
class
=
"no"
></
Label
>
<
Label
#yes
col
=
"1"
text
=
"yes, please!"
class
=
"yes"
></
Label
>
</
GridLayout
>
</
AbsoluteLayout
>
</
StackLayout
>
@ViewChild(
"absolutelayout"
) al: ElementRef;
@ViewChild(
"yes"
) yes: ElementRef;
@ViewChild(
"no"
) no: ElementRef;
...
ngOnInit() {
this
.emoji =
this
.cardService.getEmoji();
//initial card
this
.code =
this
.emoji[
this
.i].code;
//get ready for the swiping!
for
(
var
key
in
this
.emoji) {
this
.handleSwipe(key);
}
}
handleSwipe(key: any) {
this
.i--;
let grid =
new
GridLayout();
let emoji =
new
Label();
let yes = <Label>
this
.yes.nativeElement;
let no = <Label>
this
.no.nativeElement;
let absolutelayout = <AbsoluteLayout>
this
.al.nativeElement;
let swipeleft = <Button>
this
.swipeleft.nativeElement;
let swiperight = <Button>
this
.swiperight.nativeElement;
//set the emoji on the card
emoji.text =
this
.emoji[key].code;
//build the grid which is the card
grid.cssClass =
'card '
+
this
.emoji[key].color;
grid.id =
'card'
+ Number(key);
grid.marginTop =
this
.i;
//add the emoji to the grid, and the grid to the absolutelayout
grid.addChild(emoji);
absolutelayout.addChild(grid)
...
}
grid.on(GestureTypes.swipe,
function
(args: SwipeGestureEventData) {
if
(args.direction == 1) {
//right
yes.animate({ opacity: 0, duration: 100 })
.then(() => yes.animate({ opacity: 1, duration: 100 }))
.then(() => yes.animate({ opacity: 0, duration: 100 }))
.then(() =>
grid.animate({ translate: { x: 1000, y: 100 } })
.then(
function
() {
return
grid.animate({ translate: { x: 0, y: -2000 } }); })
.
catch
(
function
(e) {
console.log(e.message);
})
)
.
catch
((e) => {
console.log(e.message);
});
}
else
{
//left
no.animate({ opacity: 0, duration: 100 })
.then(() => no.animate({ opacity: 1, duration: 100 }))
.then(() => no.animate({ opacity: 0, duration: 100 }))
.then(() =>
grid.animate({ translate: { x: -1000, y: 100 } })
.then(
function
() {
return
grid.animate({ translate: { x: 0, y: -2000 } }); })
.
catch
(
function
(e) {
console.log(e.message);
})
)
.
catch
((e) => {
console.log(e.message);
});
}
});