Playing fairly….

How to master the Boarding Pass Vignette (by gskinner team)…Hmmm


For Flutter Interact ’19, Google challenged gskinner to showcase the Flutter framework’s capabilities to build beautiful apps.

What are we covering today…?

Flutter Vignette (Boarding Pass)….
Flutter Vignette (Boarding Pass)….


This tutorial is divided into 4 steps :

  1. Boarding Pass UI as per Vignette
  2. Folding/Unfolding of the Boarding Pass
  3. Theming of the pass
  4. Scrolling to the open pass…

Step 1 :

Data part is static and is taken from the original source code….

We replicate the data for 4 cards (static data)….

Flutter Vignette (Boarding Pass)….Step 1
Flutter Vignette (Boarding Pass)….Step 1

One card is a Column of 

  • LogoHeader (Fluttair)
  • Separator (Thin Black color)
  • Ticket Header (PassengerName and Boarding Time) (which itself is a row)
  • Stack of children (Origin, Duration and Destination)
  • BottomIcon (Keyboard arrowdown)
 Step1 Source Code…
 Step1 Source Code…

For the airplane, when a ticket is clicked, an animation gets triggered…

Animation in Step 1….
Animation in Step 1….

Basically, the flight slides from one position to another…

Here, is the Source Code for Step 1 

Step 2 :

We focus on the folding/unfolding of the card….

Introduce a class called FoldEntry

FoldEntry class…
FoldEntry class…

Parameters for Transform Widget :

  • alignment : Alignment of the origin (Our case
  • transform : Matrix to transform…
  • child : Widget on which Transformation occurs

Note: For details about the number (3, 2, 0.001) refer this…..

On the click of the card, we encapsulate the clicking as 

Clicking of the card….
Clicking of the card….

_getEntries() function comprises of the FoldEntry widgets….

List<FoldEntry> _getEntries() {
return [
FoldEntry(height: 160.0, front: topCard),
FoldEntry(height: 160.0, front: middleCard, back: frontCard),

For every back parameter, there will be a flip (3d)…. We have currently 2 items in the List<FoldEntry>, namely 

  • Flight Summary (From where to where)
  • Flight Details (Gate, seat number etc) (flight_details.dart)
Step 2 : Flutter Vignette (Boarding Pass)
Step 2 : Flutter Vignette (Boarding Pass)

isOpen parameter is responsible for playing the animation (flight animation), when the card is not clicked no animation takes place, but once clicked flight animation triggers……

FoldingTicket is a Stateful widget, which adjusts the height of the card, i.e expand the child height when opened vs closed…It does that while playing some animation….

Step 2: FoldingTicket…..
Step 2: FoldingTicket…..

Here, is the source code for Step 2…..

Step 3:

We include the third entry into the _getEntries function

List<FoldEntry> _getEntries() {
return [
FoldEntry(height: 160.0, front: topCard),
FoldEntry(height: 160.0, front: middleCard, back: frontCard),
FoldEntry(height: 80.0, front: bottomCard, back: backCard)

This third entry is the barcode widget, (flight_barcode.dart). As the barcode widget only contains image, hence the height is 80.0

This step also includes the theming (see below),

Step 3: Flutter Vignette (Boarding Pass)
Step 3: Flutter Vignette (Boarding Pass)

Once the card is clicked, background and text color changes to incorporate as per the dark theme.

Step 3 : Flutter Vignette (Boarding Pass)
Step 3 : Flutter Vignette (Boarding Pass)
enum SummaryTheme { dark, light }

As the card is clicked, we set the theme and let the widget take care of the displaying (as per theme)…

Step 3 : Theming…..
Step 3 : Theming…..

Here, is the source code for step 3.

Step 4 :

Till now, whenever the card was clicked, it displayed the animation or folding/unfolding, but if the card was in focus, it would certainly go out of the selection area…

This step not only respects previous steps, but also makes sure that the card selected always remain in focus…

Introducing ScrollControllers….

Step 4 : Scroll Controllers…..
Step 4 : Scroll Controllers…..

We can move to a particular position using ScrollController as 

_controller.animateTo('Offset in double',
curve: Curves.linear, duration: Duration (milliseconds: 500));


_controller.jumpTo('Offset in double');

For getting the offset in our case, some calculations was involved, but these calculations depend entirely on the params, which programmer sets…

Hence, no hard and fast rule….

Final source code, here….


Valuable comments