android development
development
flutter
flutter app development
flutter dart
flutter scan qr codes
ios development
Create a QR based Identification Scanner App with Flutter
Icons made by phatplus, Vectors Market and Nikita Golubev from www.flaticon.com
I had the idea and the code ready to create the app, but I didn't have a nice design. If you see my previous posts, it is pretty clear that all the apps lack design. Luckily there are some people on Reddit that posts Flutter UI tutorials, which help me to save time and money. For this app, I used one of cybdom flutter designs: Flight Ticket App (my favorite btw) because looks and feels like a native app. Let's get started!
1. First, let's clone the Flight App UI project
2. Open the project with Visual Studio Code
3. Inside lib, create a models folder, and inside it, create a users.dart file:
4. Create the UsersModel, which will help us to find the user when we scan a QR code. Add the id, name, and userName, email and phone. Also add a Map from Json:
This file contains 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
class UsersModel { | |
int id; | |
String name; | |
String userName; | |
String email; | |
String phone; | |
UsersModel( | |
this.id, | |
this.name, | |
this.userName, | |
this.email, | |
this.phone, | |
); | |
UsersModel.fromJson(Map json) | |
: id = json['id'], | |
name = json['name'], | |
userName = json['username'], | |
email = json['email'], | |
phone = json['phone']; | |
Map toJson() { | |
return { | |
'id': id, | |
'name': name, | |
'username': userName, | |
'email' : email, | |
'phone' : phone, | |
}; | |
} | |
} |
This file contains 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
import 'dart:async'; | |
import 'package:http/http.dart' as http; | |
const api_v1 = "https://jsonplaceholder.typicode.com"; | |
class UsersList { | |
static Future getActiveUsers() { | |
var urlUsrList = api_v1 + "/users"; | |
return http.get(urlUsrList); | |
} | |
} |
This file contains 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
qrscan: ^0.2.17 | |
http: ^0.12.0+2 |
8. Import the following libraries/packages:
This file contains 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
import 'package:qrscan/qrscan.dart' as scanner; | |
import 'dart:async'; | |
import 'dart:convert'; | |
import 'package:flight_app/api/active_users_api.dart'; | |
import 'package:flight_app/models/users.dart'; |
This file contains 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
var activeUsers = new List<UsersModel>(); | |
Timer timer; | |
int _active = 0; | |
String barcode = ''; |
This file contains 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
Future _getFromApi() async { | |
UsersList.getActiveUsers().then((response) { | |
setState(() { | |
Iterable list = json.decode(response.body); | |
activeUsers = list.map((model) => UsersModel.fromJson(model)).toList(); | |
}); | |
}); | |
} |
This file contains 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
initState() { | |
super.initState(); | |
_getFromApi(); | |
timer = Timer.periodic(Duration(seconds: 15), (Timer t) => _getFromApi()); | |
} |
This file contains 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
Future _scanFromCamera() async { | |
print('testing'); | |
String barcode = await scanner.scan(); | |
setState(() => this.barcode = barcode); | |
} |
This file contains 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
Future _scanFromCamera() async { | |
print('testing'); | |
String barcode = await scanner.scan(); | |
setState(() => this.barcode = barcode); | |
for (int i = 0; i < activeUsers.length; i++) { | |
if (activeUsers[i].id.toString() == barcode) { | |
Navigator.push( | |
context, | |
MaterialPageRoute( | |
builder: (ctx) => DetailsScreen(id: i, user: activeUsers), | |
), | |
); | |
} | |
} | |
} |
This file contains 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
import 'package:flutter/material.dart'; | |
import 'package:flight_app/global.dart'; | |
import 'package:flight_app/ui/widgets/widgets.dart'; | |
class DetailsScreen extends StatelessWidget { | |
final int id; | |
final user; | |
const DetailsScreen({Key key, @required this.id, this.user}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
backgroundColor: Color.fromRGBO(49, 57, 69, 0.9), | |
automaticallyImplyLeading: true, | |
centerTitle: true, | |
title: Text("VISITOR INFORMATION"), | |
elevation: 0.0, | |
actions: <Widget>[ | |
IconButton( | |
icon: Icon(Icons.save), | |
onPressed: () {}, | |
) | |
], | |
), | |
body: Stack( | |
children: <Widget>[ | |
Positioned.fill( | |
child: Column( | |
children: <Widget>[ | |
Flexible( | |
flex: 1, | |
child: Container( | |
color: Color.fromRGBO(49, 57, 69, 0.9), | |
), | |
), | |
Flexible( | |
flex: 2, | |
child: Container(), | |
) | |
], | |
), | |
), | |
Positioned.fill( | |
child: Container( | |
height: double.infinity, | |
margin: EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0), | |
decoration: BoxDecoration( | |
boxShadow: [ | |
BoxShadow( | |
color: Colors.black45, | |
blurRadius: 7.0, | |
offset: Offset(0, 3), | |
) | |
], | |
borderRadius: BorderRadius.circular(15.0), | |
color: Color(0xfff7f9ff)), | |
child: Column( | |
children: <Widget>[ | |
Container( | |
padding: const EdgeInsets.symmetric( | |
horizontal: 15.0, vertical: 25.0), | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.only( | |
topLeft: Radius.circular(15.0), | |
topRight: Radius.circular(15.0)), | |
gradient: LinearGradient( | |
begin: Alignment.topCenter, | |
end: Alignment.bottomCenter, | |
colors: [Color.fromRGBO(49, 57, 69, 0.9), Color(0xfff7f9ff)], | |
), | |
), | |
), | |
Container( | |
margin: EdgeInsets.symmetric(vertical: 15.0), | |
padding: const EdgeInsets.all(15.0), | |
color: Colors.white, | |
child: Column( | |
children: <Widget>[ | |
PassengerContainer( | |
id: "${user[id].id}", | |
imageUrl: userimageUrl, | |
fullName: "${user[id].name}", | |
email: "${user[id].email}", | |
phone: "${user[id].phone}", | |
username: "${user[id].userName}", | |
), | |
Divider(), | |
], | |
), | |
), | |
Image.network(boardingpassImg), | |
], | |
), | |
), | |
) | |
], | |
), | |
); | |
} | |
} | |
class FlightInfoRow extends StatelessWidget { | |
final String title, content; | |
const FlightInfoRow({Key key, this.title, this.content}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: <Widget>[ | |
Text( | |
"$title", | |
style: Theme.of(context).textTheme.body1.apply(color: Colors.black45), | |
), | |
SizedBox( | |
height: 3.0, | |
), | |
Text( | |
"$content", | |
style: Theme.of(context).textTheme.title.apply(color: Colors.black87), | |
) | |
], | |
); | |
} | |
} |
This file contains 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
import 'package:flutter/material.dart'; | |
class PassengerContainer extends StatelessWidget { | |
final String imageUrl, fullName, id, email, phone, username; | |
const PassengerContainer( | |
{Key key, this.imageUrl, this.fullName, this.id, this.email, this.phone, this.username}) | |
: super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
CircleAvatar( | |
backgroundImage: NetworkImage(imageUrl), | |
), | |
Spacer( | |
flex: 1, | |
), | |
FittedBox( | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: <Widget>[ | |
Text( | |
fullName, | |
style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold), | |
), | |
Text( | |
"Username: $username", | |
style: TextStyle(fontSize: 13.0), | |
), | |
Text( | |
"Identification number: $id", | |
style: TextStyle(fontSize: 13.0), | |
), | |
Text( | |
"Email: $email", | |
style: TextStyle(fontSize: 13.0), | |
), | |
Text( | |
"Phone number: $phone", | |
style: TextStyle(fontSize: 13.0), | |
), | |
], | |
), | |
), | |
Spacer( | |
flex: 3, | |
), | |
], | |
); | |
} | |
} |
18. As you can see, there are few explanations about the code and that's because it is mostly copy and paste from previous posts I linked at the beginning of this post. As you can see, Flutter is extremely flexible. I could just grab a Flutter design from github and integrate already working code in just few steps.
You can grab the full code for this app here: Card Scanner App UI
Also, you can view the article about the original design here: Flight Ticket App
This concludes the Create a QR based Identification Scanner App with Flutter tutorial. If you have questions, drop a comment below!
No comments
Post a Comment