๋ด ๋ ์จ๊ฐ ์ง๋๊ณ ๊ฝ๊ฐ๋ฃจ์ ๋ฌด์ฐจ๋ณ ๊ณต๊ฒฉ์ด ๋ฉ์ถ๊ณ ๋๋, ๋น์ผ์ ์๋ฏผํ ๋์ ์ฝ๋ ์ด๋ ์ ๋ ํ๋ณต์ด ๋์ด๊ฐ๊ณ ์์๋ค.
์ถ๋์ฆ์ผ๋ก ๊ณ ์ํ ์ ์ด ์์ด ์ฝ์ ๋ณต์ฉํด๊ฐ๋ฉฐ ๋น ๋ฅด๊ฒ ์น๋ฃ๋ฅผ ์งํํด์จ ๋์ ํฐ ๋ฌธ์ ์์ด ์จ์ ์ฐ๋ค๋ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ฅ๋ฐ์ผ๋ฉฐ ์ด ์ ์๊ฒ ๋์๋ค. ๋ด๋ ์ด๋ง๋ ๋๋ค์ ์ ์์ด ์์๋๊ฒ ์ง.
์ฌ๋ด์ ์ฌ๊ธฐ๊น์ง ํ๊ณ ์ด๋ฒ์๋ QR์ฝ๋๋ก ํน์ ๋จ์ด๋ฅผ ์ถ์ถํด์ค๋ ๊ธฐ๋ฅ์ ๊ตฌํํด๋ณด๋ ค ํ๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ ํ์ฌ Flutter์์ ๊ฐ์ฅ ๋ณดํธ์ ์ผ๋ก ์ฌ์ฉ๋๊ณ ์๋ ํ๋ฌ๊ทธ์ธ์ธ qr_code_scanner๋ฅผ ์ด์ฉํด๋ณด๋ ค ํ๋ค.
https://pub.dev/packages/qr_code_scanner
๋๋ ์ฌ๊ธฐ์ ๊ฐ์ฅ ์์ ํ๋์ด ๋ณด์ด๋ ๋ฒ์ ์ธ 0.6.1์ ๊ฐ์ ธ๋ค ์ธ ๊ฒ์ด๋ค.
pubspect.yaml ์์ ์๋์ ๊ฐ์ด ์์กด์ฑ์ ์ถ๊ฐํด์ฃผ๋๋ก ํ์.
๊ทธ๋ฆฌ๊ณ ํด๋น ํ๋ฌ๊ทธ์ธ์ minSdkVersion ์ด 20๋ถํฐ์ด๊ธฐ ๋๋ฌธ์
์ฑ ์์ค์ build.gradle ์์ผ๋ก ์ด๋ํ์ฌ minSdkVversion์ 20์ผ๋ก ๋ง์ถ๋๋ก ํ๋ค.
๊ทธ๋ค์ ์ฝํ๋ฆฐ ๋ฒ์ ๋ ์ต์ 1.5.1์ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ ๋น๋ ์์ค์ build.gradle์ ์ฝํ๋ฆฐ ๋ฒ์ ๋ ์์ ํ๋ค.
์ด์ ํฐ๋ฏธํธ์์ flutter clean์ ํด์ค ํ pub-get์ ํ์.
๋น๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ํ์ธํ๊ณ ๊ตฌ๊ธ๋ง์ ํ๋๋ก ํ์.
์ด์ ํ๋ฌ๊ทธ์ธ ์ธํ ์ ์๋ฃํ์์ผ๋ ๊ธฐ๋ณธ ํ๋ฉด์ ๋ง๋ค์ด์ฃผ๋๋ก ํ์.
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'QRํ'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String qrResult = '';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'์ฌ๊ธฐ์ ๋งํฌ๊ฐ ๋จ๊ฒ ๋ฉ๋๋ค.',
),
Text(
qrResult,
style: Theme.of(context).textTheme.bodyText2,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _onPressedFAB,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void _onPressedFAB() async{
}
}
main.dart ํ๋ฉด
์ด์ ์ ์๋ ์๋ FloatingActionButton์ ํด๋ฆญํ๊ฒ ๋๋ฉด QR ์ค์บ ํ๋ฉด์ผ๋ก ์ด๋๋๊ฒ ํด์ผ ๋๋๋ฐ ์ฐ์ QR ์ค์บ ํ๋ฉด์ ๋ง๋ค์ด ์ฃผ๋๋ก ํ์.
qr_check_screen.dart
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class QRCheckScreen extends StatefulWidget {
static const String ROUTE_NAME = '/qr_check_screen';
final String eventKeyword; //๊ฑด์ ธ์ฌ ํน์ ํค์๋
QRCheckScreen({required this.eventKeyword});
@override
State<QRCheckScreen> createState() => _QRCheckScreenState();
}
class _QRCheckScreenState extends State<QRCheckScreen> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
QRViewController? controller;
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(title: Text('QR์ค์บ๋'),),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
child: QRView(
key: qrKey,
onQRViewCreated: this._onQRViewCreated,
formatsAllowed: [
BarcodeFormat.qrcode
],
overlay: QrScannerOverlayShape(
borderRadius: 10,
borderColor: Colors.blue,
borderLength: 30,
borderWidth: 5,
cutOutSize: screenSize.width/1.4,
),
),
),
)
],
));
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((event) {
print('QRCheckScreen_onQRViewCreated.listen : result=${event.code}');
if (event.code != null) {
//์ค์บ๋ QR์ฝ๋์ ํน์ ํค์๋๊ฐ ๋ค์ด์๋ค๋ฉด
//QR์ค์บ์ ์ ์งํ๊ณ ์ด ํ๋ฉด์ ๋ซ์ผ๋ฉด์ QR๊ฒฐ๊ณผ๊ฐ์ ๋ณด๋ด์ฃผ๋๋กํ๋ค.
if (event.code!.contains(widget.eventKeyword)) {
this.controller!.dispose();
Navigator.pop(context, event.code);
}
}
});
}
}
์ฝ๋์ ์ฃผ์์ผ๋ก ์ค๋ช ์ ํด๋๊ธด ํ์ง๋ง ์กฐ๊ธ ๋ ์ค๋ช ์ด ํ์ํ ๊ฒ ๊ฐ๋ค.
์ฐ์ ๋งจ ์์
class QRCheckScreen extends StatefulWidget {
static const String ROUTE_NAME = '/qr_check_screen';
final String eventKeyword; //๊ฑด์ ธ์ฌ ํน์ ํค์๋
QRCheckScreen({required this.eventKeyword});
@override
State<QRCheckScreen> createState() => _QRCheckScreenState();
}
์ด ๋ถ๋ถ์์๋ QR์ฝ๋ ์ค์บ๋๊ฐ ์ฐ์์ผ๋ก ์๋๋๊ธฐ ๋๋ฌธ์ QR์ด ์ธ์๋ ๋๋ง๋ค 0.1์ด ๋จ์๋ก ๊ฒฐ๊ด๊ฐ์ ์ถ๋ ฅํ๋
์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํจ๋ค. ๋ฐ๋ผ์ ๋ด๊ฐ ์ป๊ณ ์ ํ๋ ํน์ ํค์๋๋ฅผ ์ง์ ํด์ฃผ์ด์ผ ํ๋๋ฐ ์ ์ฝ๋์์ ์์ฑ์๋ฅผ ํธ์ถํ ๋ ๊ฐ์ ์ง์ ํ๋๋ก ํ๋ค.
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((event) {
print('QRCheckScreen_onQRViewCreated.listen : result=${event.code}');
if (event.code != null) {
//์ค์บ๋ QR์ฝ๋์ ํน์ ํค์๋๊ฐ ๋ค์ด์๋ค๋ฉด
//QR์ค์บ์ ์ ์งํ๊ณ ์ด ํ๋ฉด์ ๋ซ์ผ๋ฉด์ QR๊ฒฐ๊ณผ๊ฐ์ ๋ณด๋ด์ฃผ๋๋กํ๋ค.
if (event.code!.contains(widget.eventKeyword)) {
this.controller!.dispose();
Navigator.pop(context, event.code);
}
}
});
}
๊ทธ๋ฆฌ๊ณ ์ด ๋ถ๋ถ์์๋ qrView๊ฐ ์์ฑ๋๋ ๋์์ onQRViewCreated๋ฅผ ํธ์ถํ๋๋ก ํ๋ค.
๊ทธ๋ฆฌ๊ณ QRViewController๋ฅผ ์ธ์๋ก ๊ฑด๋ค์ฃผ์ด ์ํ๋ ์ก์ ์ ์ํํ ์ ์๋๋ก ๋์์ค๋ค.
์ฌ๊ธฐ์ QRViewController์ listner์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด
event๋ผ๋ ์ธ์๋ฅผ ๋ฐ๊ฒ ๋๊ณ ํด๋น ์ธ์๊ฐ null์ด ์๋๊ณ ์ด์ ์ ์ง์ ํ keyword ๊ฐ ๊ฒฐ๊ด๊ฐ์ ํฌํจ๋์ด ์๋ค๋ฉด
QRViewController๋ฅผ ์ข ๋ฃํ๊ณ ํ๋ฉด์ ๋ซ์ผ๋ฉด์ ๊ฒฐ๊ด๊ฐ์ ๋ณด๋ด๋๋ก ์ง์ ํ๊ณ ์๋ค.
์ด์ ๋ค์ main.dart๋ก ์ด๋ํ์ฌ
FloatingActionButton์ ๋๋ฅด๋ฉด QR์ค์บ๋ ํ๋ฉด์ผ๋ก ์ด๋ํ๋๋ก ๊ตฌํํ์.
main.dart
void _onPressedFAB() async { //๋น๋๊ธฐ ์คํ์ผ๋ก QRํ๋ฉด์ด ๋ซํ๊ธฐ ์ ๊น์ง await์ผ๋ก ๊ธฐ๋ค๋ฆฌ๋๋ก ํ๋ค.
dynamic result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return QRCheckScreen(eventKeyword: 'userId');
}));
if(result != null) {
setState(() {
//qr์ค์บ๋์์ ๋ฐ์ ๊ฒฐ๊ณผ๊ฐ์ ํ๋ฉด์ qrResult ์ ์ ์ฉํ๋๋ก ํ๋ค.
qrResult = result.toString();
});
}
}
}
์ด์ ์คํํด์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณด์.
์ฒซ ๋ฒ์งธ qr์ฝ๋๋ userId๊ฐ ํฌํจ๋ url๋งํฌ์ด๊ณ
๋ ๋ฒ์งธ qr์ฝ๋๋ userId๊ฐ ํฌํจ๋์ง ์์ url๋งํฌ์ด๋ค.
์ธ ๋ฒ์งธ๋ text๋ง์ ์ด์ฉํด userId๋ฅผ ํฌํจํ์ฌ ์ธ์์ ์์ผ๋ดค๋ค.
๋ณธ์ธ์ด ์ํ๋ ํ๋ผ๋ฏธํฐ๋ก ์ง์ ํ ์ ์๊ณ ์ค์บ ๊ฒฐ๊ณผ๋ ๋ง์๋๋ก ์กฐ์ํ์ฌ ๋ค๋ฃฐ ์ ์์ ๊ฒ์ด๋ค.
์ด๋ฒ ํฌ์คํ ์ ์ฌ๊ธฐ๊น์ง.
์๋๋ ์ฑ ์ ์ฒด ์์ค์ฝ๋์ด๋ค.
https://github.com/jwk9022648/flutter_qr_test