나무야3
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
BIN
assets/images/Main_Back.webp
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 20 KiB |
@@ -5,24 +5,29 @@ class Assets {
|
||||
static const String audio001 = 'assets/audio/001.wav';
|
||||
static const String audio002 = 'assets/audio/002.wav';
|
||||
static const String audio003 = 'assets/audio/003.wav';
|
||||
static const String images001 = 'assets/images/001.jpg';
|
||||
static const String images002 = 'assets/images/002.jpg';
|
||||
static const String images003 = 'assets/images/003.jpg';
|
||||
static const String images004 = 'assets/images/004.jpg';
|
||||
static const String images005 = 'assets/images/005.jpg';
|
||||
static const String images006 = 'assets/images/006.jpg';
|
||||
static const String images007 = 'assets/images/007.jpg';
|
||||
static const String images008 = 'assets/images/008.jpg';
|
||||
static const String images009 = 'assets/images/009.jpg';
|
||||
static const String imagesBackground = 'assets/images/background.jpg';
|
||||
static const String imagesSwith01 = 'assets/images/swith01.png';
|
||||
static const String imagesSwith02 = 'assets/images/swith02.png';
|
||||
static const String imagesSwith03 = 'assets/images/swith03.png';
|
||||
static const String imagesSwith04 = 'assets/images/swith04.png';
|
||||
static const String imagesSwith05 = 'assets/images/swith05.png';
|
||||
static const String imagesSwith06 = 'assets/images/swith06.png';
|
||||
static const String imagesSwith07 = 'assets/images/swith07.png';
|
||||
static const String imagesSwith08 = 'assets/images/swith08.png';
|
||||
static const String imagesSwith09 = 'assets/images/swith09.png';
|
||||
static const String goSubsetsButton01 = 'assets/images/go_subsets/Button_01.webp';
|
||||
static const String goSubsetsButton02 = 'assets/images/go_subsets/Button_02.webp';
|
||||
static const String goSubsetsButton03 = 'assets/images/go_subsets/Button_03.webp';
|
||||
static const String goSubsetsButton04 = 'assets/images/go_subsets/Button_04.webp';
|
||||
static const String goSubsetsButton05 = 'assets/images/go_subsets/Button_05.webp';
|
||||
static const String goSubsetsButton06 = 'assets/images/go_subsets/Button_06.webp';
|
||||
static const String goSubsetsButton07 = 'assets/images/go_subsets/Button_07.webp';
|
||||
static const String goSubsetsButton08 = 'assets/images/go_subsets/Button_08.webp';
|
||||
static const String goSubsetsButton09 = 'assets/images/go_subsets/Button_09.webp';
|
||||
static const String imagesMainBack = 'assets/images/Main_Back.webp';
|
||||
static const String subsetsSub01 = 'assets/images/subsets/Sub_01.webp';
|
||||
static const String subsetsSub02 = 'assets/images/subsets/Sub_02.webp';
|
||||
static const String subsetsSub03 = 'assets/images/subsets/Sub_03.webp';
|
||||
static const String subsetsSub04 = 'assets/images/subsets/Sub_04.webp';
|
||||
static const String subsetsSub05 = 'assets/images/subsets/Sub_05.webp';
|
||||
static const String subsetsSub06 = 'assets/images/subsets/Sub_06.webp';
|
||||
static const String subsetsSub07 = 'assets/images/subsets/Sub_07.webp';
|
||||
static const String subsetsSub08 = 'assets/images/subsets/Sub_08.webp';
|
||||
static const String subsetsSub09 = 'assets/images/subsets/Sub_09.webp';
|
||||
static const String uiUI5minus = 'assets/images/ui/UI_5minus.webp';
|
||||
static const String uiUI5plus = 'assets/images/ui/UI_5plus.webp';
|
||||
static const String uiUIBack = 'assets/images/ui/UI_Back.webp';
|
||||
static const String uiUIPlay = 'assets/images/ui/UI_Play.webp';
|
||||
static const String uiUIReplay = 'assets/images/ui/UI_Replay.webp';
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:poet/poet_screen.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
@@ -18,7 +21,41 @@ class MyApp extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class PoetStudyScreen extends StatelessWidget {
|
||||
class PoetStudyScreen extends StatefulWidget {
|
||||
@override
|
||||
_PoetStudyScreenState createState() => _PoetStudyScreenState();
|
||||
}
|
||||
|
||||
class _PoetStudyScreenState extends State<PoetStudyScreen>
|
||||
with WidgetsBindingObserver {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_setSystemUIOverlayStyle();
|
||||
}
|
||||
|
||||
void _setSystemUIOverlayStyle() {
|
||||
if (Platform.isAndroid) {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
// When the main screen is disposed, restore the system UI
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
_setSystemUIOverlayStyle();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -27,7 +64,7 @@ class PoetStudyScreen extends StatelessWidget {
|
||||
// Background Image
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/images/background.jpg',
|
||||
'assets/images/Main_Back.webp',
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
@@ -66,9 +103,6 @@ class PoetStudyScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildGridItem(BuildContext context, int index) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
String imageName = 'swith${(index + 1).toString().padLeft(2, '0')}';
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
@@ -80,25 +114,13 @@ class PoetStudyScreen extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 5,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/$imageName.png',
|
||||
width: screenWidth * 0.25,
|
||||
height: screenWidth * 0.25,
|
||||
'assets/images/go_subsets/Button_${(index + 1).toString().padLeft(2, '0')}.webp',
|
||||
width: 325,
|
||||
height: 325,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
],
|
||||
@@ -106,4 +128,4 @@ class PoetStudyScreen extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class PoetScreen extends StatefulWidget {
|
||||
State<PoetScreen> createState() => _PoetScreenState();
|
||||
}
|
||||
|
||||
class _PoetScreenState extends State<PoetScreen> {
|
||||
class _PoetScreenState extends State<PoetScreen> with WidgetsBindingObserver {
|
||||
late String _backgroundImage;
|
||||
final AudioPlayer _audioPlayer = AudioPlayer();
|
||||
bool _isPlaying = false;
|
||||
@@ -25,11 +25,11 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (Platform.isAndroid) {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
||||
}
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_setSystemUIOverlayStyle();
|
||||
|
||||
_backgroundImage =
|
||||
'assets/images/00${(widget.selectedIndex + 1).toString()}.jpg';
|
||||
'assets/images/subsets/Sub_${(widget.selectedIndex + 1).toString().padLeft(2, '0')}.webp';
|
||||
_source = AssetSource('audio/00${(widget.selectedIndex + 1).toString()}.wav');
|
||||
|
||||
_audioPlayer.onPlayerStateChanged.listen((state) {
|
||||
@@ -66,6 +66,19 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
_setAudio();
|
||||
}
|
||||
|
||||
void _setSystemUIOverlayStyle() {
|
||||
if (Platform.isAndroid) {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
_setSystemUIOverlayStyle();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _setAudio() async {
|
||||
try {
|
||||
await _audioPlayer.setSource(_source);
|
||||
@@ -77,6 +90,7 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
if (Platform.isAndroid) {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
}
|
||||
@@ -110,11 +124,13 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_buildCircularButton(Icons.arrow_back, () {
|
||||
_buildCircularImageButton('assets/images/ui/UI_Back.webp', () {
|
||||
// 이 버튼을 누르면 이전 화면으로 돌아갑니다.
|
||||
Navigator.pop(context);
|
||||
}, size: 50, iconSize: 25),
|
||||
_buildCircularButton(Icons.refresh, () {}, size: 50, iconSize: 25),
|
||||
}, size: 50, imageSize: 25),
|
||||
_buildCircularImageButton('assets/images/ui/UI_Replay.webp', () {
|
||||
// Refresh action here
|
||||
}, size: 50, imageSize: 25),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -157,24 +173,14 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildCircularButton(Icons.replay_5, () {
|
||||
_buildCircularImageButton('assets/images/ui/UI_5minus.webp', () {
|
||||
final newPosition = _position - const Duration(seconds: 5);
|
||||
_audioPlayer.seek(newPosition > Duration.zero ? newPosition : Duration.zero);
|
||||
}),
|
||||
const SizedBox(width: 16),
|
||||
_buildCircularButton(_isPlaying ? Icons.pause : Icons.play_arrow, () {
|
||||
if (_isPlaying) {
|
||||
_audioPlayer.pause();
|
||||
} else {
|
||||
if (_playerState == PlayerState.completed) {
|
||||
_audioPlayer.play(_source);
|
||||
} else {
|
||||
_audioPlayer.resume();
|
||||
}
|
||||
}
|
||||
}),
|
||||
_buildPlayPauseButton(),
|
||||
const SizedBox(width: 16),
|
||||
_buildCircularButton(Icons.forward_5, () {
|
||||
_buildCircularImageButton('assets/images/ui/UI_5plus.webp', () {
|
||||
final newPosition = _position + const Duration(seconds: 5);
|
||||
_audioPlayer.seek(newPosition < _duration ? newPosition : _duration);
|
||||
}),
|
||||
@@ -184,6 +190,62 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPlayPauseButton() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (_isPlaying) {
|
||||
_audioPlayer.pause();
|
||||
} else {
|
||||
if (_playerState == PlayerState.completed) {
|
||||
_audioPlayer.play(_source);
|
||||
} else {
|
||||
_audioPlayer.resume();
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 80,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF07B41),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
),
|
||||
child: Center(
|
||||
child: _isPlaying
|
||||
? const Icon(Icons.pause, color: Colors.white, size: 50)
|
||||
: Image.asset(
|
||||
'assets/images/ui/UI_Play.webp',
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCircularImageButton(String imagePath, VoidCallback onPressed, {double size = 80, double imageSize = 50}) {
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF07B41),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
),
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
imagePath,
|
||||
width: imageSize,
|
||||
height: imageSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _formatDuration(Duration duration) {
|
||||
String twoDigits(int n) => n.toString().padLeft(2, '0');
|
||||
final hours = twoDigits(duration.inHours);
|
||||
@@ -196,21 +258,5 @@ class _PoetScreenState extends State<PoetScreen> {
|
||||
].join(':');
|
||||
}
|
||||
|
||||
// 원형 버튼을 만드는 헬퍼 함수
|
||||
Widget _buildCircularButton(IconData icon, VoidCallback onPressed, {double size = 80, double iconSize = 50}) {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF07B41),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: onPressed,
|
||||
icon: Icon(icon, color: Colors.white),
|
||||
iconSize: iconSize,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ flutter:
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- assets/images/ # 이 경로가 꼭 포함되어야 합니다.
|
||||
- assets/images/
|
||||
- assets/images/go_subsets/
|
||||
- assets/images/subsets/
|
||||
- assets/images/ui/
|
||||
- assets/icons/
|
||||
- assets/audio/
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
|
||||