스플래시 화면에 보여줄 이미지를 준비합니다.
스플래시 화면은 일반적으로 앱 로고 또는 홍보 이미지를 사용합니다.
main.dart 파일에서 스플래시 화면을 표시할 위젯을 생성합니다.
보통 MaterialApp 위젯을 감싸는 형태로 스플래시 화면을 만듭니다.
스플래시 화면 위젯 내부에서 Future.delayed 함수를 사용하여 지정된 시간 동안 스플래시 화면을 보여준 후에 다음 화면으로 이동하도록 처리합니다.
다음 화면으로 이동하기 위해서는 Navigator 클래스의 pushReplacement 메서드를 사용하면 됩니다.
아래는 간단한 예제 코드입니다:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Splash Screen Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: const SplashScreen(), // 스플래시 화면 표시
);
}
}
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
super.initState();
_navigateToNextScreen(); // 지정된 시간 후 다음 화면으로 이동
}
Future<void> _navigateToNextScreen() async {
await Future.delayed(Duration(seconds: 2)); // 2초 동안 스플래시 화면 표시
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => MyHomePage()), // 다음 화면으로 이동
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlutterLogo(size: 100),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: Center(
child: Text('Welcome to the Main Screen!'),
),
);
}
}
위 코드에서 SplashScreen 클래스에서 initState 메서드 내부에서 _navigateToNextScreen 함수를 호출하여 스플래시 화면을 지정된 시간 동안 표시한 후에 Navigator를 사용하여 다음 화면으로 이동합니다.
MyHomePage 클래스는 메인 화면을 나타내며, Navigator를 통해 이동한 화면입니다.
스플래시 이미지 변경
pubspec.yaml 이미지 리소스 추가
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
assets:
- assets/images/splash_image.png
프로젝트 구조
스플래쉬 변경 소스
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
//child: FlutterLogo(size: 100),
child: Image(
image: AssetImage('assets/images/splash_image.png'),
)
),
);
}
전체소스
main.dart
/*
* InAppWebViewController 컨트롤러 사용
*
*/
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'SocketManager.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Splash Screen Example',
theme: ThemeData(primarySwatch: Colors.blue),
//home: const MyHomePage(title: 'Flutter Demo Home Page'),
home: const SplashScreen(),
);
}
}
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
super.initState();
_navigateToNextScreen(); // 지정된 시간 후 다음 화면으로 이동
}
Future<void> _navigateToNextScreen() async {
await Future.delayed(const Duration(seconds: 2)); // 2초 동안 스플래시 화면 표시
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => const MyHomePage(title: '',)), // 다음 화면으로 이동
);
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
//child: FlutterLogo(size: 100),
child: Image(
image: AssetImage('assets/images/splash_image.png'),
)
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final socketManager = SocketManager();
/*
* 웹뷰 컨트롤러 설정
JavaScriptMode.disabled: WebView에서 JavaScript를 비활성화합니다. 웹 페이지의 JavaScript 코드가 실행되지 않습니다.
JavaScriptMode.unrestricted: WebView에서 JavaScript를 활성화합니다. 웹 페이지의 JavaScript 코드가 실행되며, JavaScript로 인터랙티브한 동작이 가능해집니다.
setBackgroundColor(const Color(0x00000000)): 이 부분은 WebView의 배경 색상을 설정하는 것입니다. 여기서 Color(0x00000000)은 투명한 배경색을 나타냅니다. 즉, WebView가 투명한 배경을 가지게 됩니다.
*/
late final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// update loading bar.
},
onPageStarted: (String url) {
},
onPageFinished: (String url) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..addJavaScriptChannel('JsBridge', onMessageReceived: (JavaScriptMessage message) {
/*
javascript send() 클릭시 여기로 전송된다 message 는 json 형태
*/
_web2flutter(message);
})
//..setUserAgent("agent-> naya moblie_wv")
..loadRequest(
//Uri.parse('http://220.72.212.247/flutter_index2.html')
Uri.parse('http://192.168.0.6:5173/')
);
/*
addJavaScriptChannel('JsBridge', onMessageReceived: (JavaScriptMessage message) { ... }): 이 부분은 WebView에 JavaScript 채널을 추가하는 것입니다.
채널은 JavaScript와 Flutter 사이의 통신을 가능하게 해주는 메커니즘입니다.
여기서 'JsBridge'는 채널의 이름을 나타냅니다.
이 이름을 기반으로 JavaScript에서 해당 채널을 호출하고, Flutter에서 해당 채널로 메시지를 수신할 수 있습니다.
onMessageReceived: (JavaScriptMessage message) { ... }:
이 부분은 JavaScript에서 Flutter로 메시지를 전달할 때 호출되는 콜백 함수를 정의하는 것입니다.
JavaScriptMessage는 flutter_inappwebview 라이브러리에서 제공되는 클래스로서, JavaScript에서 전달된 메시지를 Flutter에서 받을 때 사용합니다.
따라서 addJavaScriptChannel을 사용하여 'JsBridge'라는 이름의 채널을 추가하고, 해당 채널로 메시지가 전달되면 onMessageReceived 콜백 함수가 호출됩니다.
이때, message 매개변수를 통해 JavaScript에서 전달된 메시지를 받을 수 있습니다.
실제 웹페이지의 javascript 확인해보면 JsBridge 로 된 메시지가 있습니다.
*/
/*
* 사용자 정의 함수
*/
_reload() {
controller.reload();
}
_web2flutter(JavaScriptMessage message) async {
/*
* json 형태를 객체로 변경
*/
Map<String, dynamic> parsedJson = jsonDecode(message.message);
var action = parsedJson['action'];
var inputHexString = parsedJson['hexString'];
print('acton:'+action);
print('inputHexString:'+inputHexString);
var receivedHexString = '';
print(action);
switch(action) {
case 'connect':
connect();
break;
case 'sendTr' :
sendTr(inputHexString);
break;
case 'bufferTest' :
bufferTest();
break;
}
}
dd(String str) {
if (kDebugMode) {
print(str);
}
}
Future<bool> _onWillPop() async {
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('종료하시겠습니까?'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: Text('아니오'),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text('예'),
),
],
),
) ?? false;
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
body: WebViewWidget(
controller: controller,
),
),
);
}
@override
void reassemble() {
super.reassemble();
_reload();
}
/*
StatefulWidget이 생성될 때 한 번 호출되는 생명주기 메서드로,
해당 위젯이 생성되었을 때 초기화 작업을 수행하는데 사용됩니다. 따라서 이곳에 초기 실행해야 할 로직을 넣으면 됩니다.
*/
@override
void initState() {
super.initState();
// 이곳에 초기 실행해야 할 로직을 추가합니다.
socketManager.connectToSocket(controller); // 소켓 접속한다.
}
Future<void> connect() async {
await socketManager.connectToSocket(controller); // 소켓 접속한다.
var receivedConnected = 'connected : ${socketManager.connected}';
print(receivedConnected);
controller.runJavaScript("flutter2web('$receivedConnected')");
}
Future<void> sendTr(sendHexString) async {
socketManager.sendTr(sendHexString); // 접속된 소켓에 데이터를 전송한다. input
}
void bufferTest() {
List<int> buffer = [0x00, 0x00, 0x07, 0x04]; // 예시 데이터
int length = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
print(buffer[0]);
print(buffer[1]);
print(buffer[2]);
print(buffer[3]);
int part1 = buffer[0] << 24; // 24비트(3byte) 왼쪽으로 이동 -> 0x 00 00 00 00 (32bit - 4byte)
int part2 = buffer[1] << 16; // 16비트(2byte) 왼쪽으로 이동 -> 0x 00 00 00 (24bit - 3byte)
int part3 = buffer[2] << 8; // 8비트(1byte) 왼쪽으로 이동 -> 0x 07 00 (16bit - 2byte)
int part4 = buffer[3]; // 그대로 사용 -> 0x 04 (8bit - 1byte)
/**
*
그럼 0x03 을 24비트 좌측 쉬프트 하면 ?
0x03 이진수로 표현 00000000 00000000 00000000 00000011
0x03 << 24
0x00 00 00 03
그럼 0x03 을 16비트 좌측 쉬프트 하면 ?
0x03 << 16
0x00 03 00 00
그럼 0x03 을 8비트 좌측 쉬프트 하면 ?
0x03 << 8
0x00 00 03 00
-------------------------------------------------------
0x00 << 24
0x00 00 00 00
0x00 << 16
0x00 00 00 00
0x07 << 8
0x00 00 07 00
0x04 그대로 사용
0x00 00 00 04
==> | or 연산하면
0x00 00 00 00
0x00 00 00 00
0x00 00 07 00
0x00 00 00 04
-------------
0x00 00 07 04
결론 0x00000704
16진수 704
10진수로 변환하면 1796
*/
// 10진수 값을 16진수 문자열로 변환
print('Part 1: ${part1}');
print('Part 1: ${part1.toRadixString(16)}');
print('Part 2: ${part2.toRadixString(16)}');
print('Part 3: ${part3.toRadixString(16)}');
print('Part 4: ${part4.toRadixString(16)}');
print('Length1: ${length.toRadixString(16)}');
print('Length2: $length');
}
}
참고
https://eunoia3jy.tistory.com/102
'프로그래밍 > flutter' 카테고리의 다른 글
[flutter] 화면의 가로 및 세로 크기를 가져오기(휴대폰/패드 등) (0) | 2023.09.26 |
---|---|
[flutter] 앱 아이콘 변경 (0) | 2023.08.16 |
[flutter] 백버튼(뒤로가기) 클릭시 "종료하시겠습니까?" 다이얼로그 추가 (0) | 2023.08.16 |
[flutter] native(앱) 의 웹뷰(vue3) 양방향 통신 방법 InAppWebView 사용 (0) | 2023.08.11 |
소켓통신 첫 4byte 길이 구하기 (비트연산) (0) | 2023.08.10 |