과제 내용
- Assignment
- 제공되는 패키지 secrets_cat_sdk를 활용하여 다음의 기대 결과물을 따라 만드세요.
- 이번 과제는 최대한 다음의 결과물과 다른 디자인으로 제작하는데 목표를 두세요.
- Requirements
- 앱 이름은 [비밀듣는 고양이]가 아닌 다른 이름으로 진행하세요.
- 앱 내에서 사용될 폰트는 다음과 같습니다.
- 플러터에 폰트 등록 방법을 검색하여 앱내에 적용할 수 있도록 하세요. neo.ttf
- 매인 캐릭터 또한 다음의 링크에서 마음에 드는 이미지를 골라서 진행하세요.
- 페이지들의 배경이미지는 다음의 링크에서 마음에 드는 이미지를 골라서 진행하세요.
- 각 위젯별 애니메이션은 최소 3개 이상이 적용되어야 합니다. 이 때 적용되는 애니메이션은 자유입니다.
- 페이지는 3개 이상입니다. 필수 페이지는 다음과 같습니다.
- SecretPage : 비밀을 볼 수 있는 페이지며, 모든 비밀을 데이터로 불러오며 각 비밀은 페이지로 이루어짐.
- AuthorPage : 모든 작성자(회원)을 볼 수 있는 페이지
- UploadPage: 비밀을 업로드할 수 있는 페이지
- 패키지를 설치하면 Author와 Secret 데이터타입을 사용할 수 있습니다.
데이터와 데이터타입을 활용하여 최대한 위 결과물의 비슷하게 앱을 만들어보세요.
assets > fonts > 파일 넣기
pubspec.yaml
fonts 주석 풀고 등록 피그마 링크 👉 비밀먹는햄버거
import 'package:first_app/homework/week4/day18/splash.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(fontFamily: 'neo'),
home: SplashScreen()
);
}
}
import 'package:first_app/homework/week4/day18/secret_hamburger.dart';
import 'package:flutter/material.dart';
class SplashScreen extends StatefulWidget {
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
void initState() {
super.initState();
Future.delayed(
Duration(seconds: 3), // 3초 동안 Splash Screen 표시
() => Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SecretHamburger()),
),
);
}
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/secret_hamburger/Splash.png'),
fit: BoxFit.fill
)
),
)
);
}
}
import 'package:first_app/homework/week4/day18/author_page.dart';
import 'package:first_app/homework/week4/day18/upload_page.dart';
import 'package:flutter/material.dart';
import 'secret_page.dart';
class SecretHamburger extends StatelessWidget {
const SecretHamburger({Key? key}) : super(key: key);
Widget build(BuildContext context) {
List menu = ['비밀 보러가기', '작성자 구경', '비밀 알려주기'];
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 50.0),
child: Image.asset('assets/images/secret_hamburger/main-icon.png'),
),
Column(
children: List.generate(
menu.length, (index) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
child: ListTile(
leading: Image.asset('assets/images/secret_hamburger/hambuug.png'),
title: Text(menu[index]),
onTap: () {
switch(index) {
case 0:
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecretPage())
);
break;
case 1:
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AuthorPage())
);
break;
case 2:
Navigator.push(
context,
MaterialPageRoute(builder: (context) => UploadPage())
);
break;
}
},
),
),
),
)
],
),
),
);
}
}
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:secret_cat_sdk/api/api.dart';
class SecretPage extends StatefulWidget {
const SecretPage({Key? key}) : super(key: key);
State<SecretPage> createState() => _SecretPageState();
}
class _SecretPageState extends State<SecretPage> {
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
foregroundColor: Colors.black,
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/secret_hamburger/SecretPage-background.png'),
fit: BoxFit.fill
)
),
child: Column(
children: [
SizedBox(height: 50),
Expanded(
child: FutureBuilder(
future: SecretCatApi.fetchSecrets(),
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.done) {
return PageView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var author = snapshot.data![index].author ?? '익명';
return Padding(
padding: const EdgeInsets.all(50.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ListTile(
leading: ZoomIn(child: SizedBox(child: Image.asset('assets/images/secret_hamburger/main-icon.png'))),
title: FadeInLeft(child: Text(author.toString())),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ZoomIn(
child: Container(
width: 200,
height: 100,
color: Colors.grey[200],
child: Text(snapshot.data![index].secret),
),
),
)
],
),
),
);
}
);
}
return Container();
}
),
),
Text('먹을게~', style: TextStyle(fontSize: 20),),
SizedBox(height: 30,)
],
),
),
);
}
}
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:secret_cat_sdk/api/api.dart';
class AuthorPage extends StatefulWidget {
const AuthorPage({Key? key}) : super(key: key);
State<AuthorPage> createState() => _AuthorPageState();
}
class _AuthorPageState extends State<AuthorPage> {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
foregroundColor: Colors.black,
backgroundColor: Colors.transparent,
elevation: 0,
),
body: FutureBuilder(
future: SecretCatApi.fetchAuthors(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return GridView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Container(
child: Column(
children: [
Flexible(
child: ZoomIn(
child: snapshot.data![index].avatar != null
? Image.network(snapshot.data![index].avatar!)
: Image.asset('assets/images/secret_hamburger/main-icon.png'),
),
),
SizedBox(height: 10),
FadeInLeft(child: Text(snapshot.data![index].username)),
],
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
);
}
return LinearProgressIndicator();
}
),
);
}
}
import 'package:flutter/material.dart';
import 'package:secret_cat_sdk/api/api.dart';
class UploadPage extends StatefulWidget {
const UploadPage({Key? key}) : super(key: key);
State<UploadPage> createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
TextEditingController textController = TextEditingController();
String hamText = '진짜\n나만 알고\n잇을게';
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(
foregroundColor: Colors.black,
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 20),
Container(
padding: EdgeInsets.symmetric(horizontal: 60),
child: Stack(
children: [
Image.asset('assets/images/secret_hamburger/UploadPage-burger.png'),
Padding(
padding: const EdgeInsets.only(left: 110.0, top: 20),
child: Align(
child: Text(hamText)
),
)
]
),
),
SizedBox(height: 50),
Container(
width: 250,
height: 200,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
child: TextField(
controller: textController,
maxLines: null,
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
hintText: '비밀을 말해보렴!!!',
border: InputBorder.none,
contentPadding: EdgeInsets.all(10),
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
setState(() {
SecretCatApi.addSecret(textController.text);
textController.text = '';
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('비밀 등록이 완료되었습니다.'),
),
);
hamText = '헤헤\n뻥이지롱';
Future.delayed(Duration(milliseconds: 1500), () {
setState(() {
hamText = '진짜\n나만 알고\n잇을게';
});
});
});
},
child: Text('비밀 등록'),),
Spacer()
],
),
),
);
}
}
gif벨로그 이미지 크기가 안줄여져요..........
비밀먹는 햄버거를 디자인하면서 나름 핵심 기능이라 생각했던 비밀 페이지의 먹을게, 뱉을게 기능(먹뱉 기능)을 구현하지 못해서 아쉽습니다
다음 페이지로 이동하는 중에는 ‘먹을게~’, 이전 페이지로 이동하는 중에는 ‘뱉을게~’, 페이지가 이동중인 상태가 아니라면 ‘짜잔’ 텍스트를 보여주는 기능인데,
많은 시도 끝에 금요일엔 포기하고 주말에 수정을 해보기로 다짐했습니다…
앱이 자꾸 빨개져요………………………………………