나무야3

This commit is contained in:
girinb
2025-09-13 22:21:24 +09:00
parent 7ac6768dec
commit b121e24a1e
24 changed files with 157 additions and 81 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -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';
}

View File

@@ -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 {
),
);
}
}
}

View File

@@ -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,
),
);
}
}
}

View File

@@ -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: