인스타그램 앱 따라 만들기
main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'body.dart';
void main() {
runApp(const InstaCloneApp());
}
class InstaCloneApp extends StatelessWidget {
const InstaCloneApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: const ColorScheme.light(
primary: Colors.white, secondary: Colors.black),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
showSelectedLabels: false,
showUnselectedLabels: false,
selectedItemColor: Colors.black
),
useMaterial3: true),
home: InstaCloneHome(),
);
}
}
class InstaCloneHome extends StatefulWidget {
const InstaCloneHome({super.key});
@override
State<InstaCloneHome> createState() => _InstaCloneHomeState();
}
class _InstaCloneHomeState extends State<InstaCloneHome> {
late int index;
@override
void initState() {
super.initState();
index = 0;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: index == 0 ?AppBar(
title: Text(
'Instagram',
style: GoogleFonts.lobsterTwo(color: Colors.black, fontSize: 32),
),
centerTitle: false,
actions: [
IconButton(
icon: const Icon(Icons.favorite_outline, size: 32,),
onPressed: () {
print('Tab favorite');
},
),
IconButton(
icon: const Icon(CupertinoIcons.paperplane, size: 32,),
onPressed: () {
print('Teb paperplane');
},
)
],
) : null,
body: InstaBody(index: index),
bottomNavigationBar: BottomNavigationBar(
currentIndex: index,
onTap: (newIndex) => setState(() => index = newIndex),
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home, size: 28,), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search, size: 28,), label: 'Search'),
],
),
);
}
}
body.dart
import 'package:flutter/material.dart';
import 'package:insta_clone/screen/home_screen.dart';
import 'package:insta_clone/screen/search_screen.dart';
class InstaBody extends StatelessWidget {
final int index;
const InstaBody({required this.index, super.key});
@override
Widget build(BuildContext context) {
if (index == 0) {
return const HomeScreen();
}
return const SearchScreen();
}
}
home_screen.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return const SingleChildScrollView(
child: Column(
children: [
StoryArea(),
FeedList()
],
),
);
}
}
class StoryArea extends StatelessWidget {
const StoryArea({super.key});
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(10, (index) => UserStory(userName: 'User $index')),
),
);
}
}
class UserStory extends StatelessWidget {
final String userName;
const UserStory({
required this.userName,
super.key,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12),
child: Column(
children: [
Container(
width: 80,
height: 80,
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.blue.shade300,
borderRadius: BorderRadius.circular(40)
),
),
Text(userName),
],
),
);
}
}
class FeedData {
final String userName;
final int likeCount;
final String content;
FeedData({required this.userName, required this.likeCount, required this.content});
}
final feedDataList = [
FeedData(userName: 'User 1', likeCount: 50, content: '오늘 점심은 맛있었다'),
FeedData(userName: 'User 2', likeCount: 20, content: '오늘 아침은 맛있었다'),
FeedData(userName: 'User 3', likeCount: 40, content: '오늘 저녁은 맛있었다'),
FeedData(userName: 'User 4', likeCount: 56, content: '오늘은 미용실을 갔다'),
FeedData(userName: 'User 5', likeCount: 32, content: '샤라랄라랄~'),
FeedData(userName: 'User 6', likeCount: 52, content: '내일은 뭐 먹지?'),
FeedData(userName: 'User 7', likeCount: 12, content: '배고픈데?'),
FeedData(userName: 'User 8', likeCount: 3, content: '오늘은 다이어트!'),
FeedData(userName: 'User 9', likeCount: 42, content: '오늘 점심은 맛있었다'),
];
class FeedList extends StatelessWidget {
const FeedList({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount:feedDataList.length, itemBuilder: (context, index) => FeedItem(feedData: feedDataList[index]),);
}
}
class FeedItem extends StatelessWidget {
final FeedData feedData;
const FeedItem({required this.feedData, super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
height: 40, width: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.blue.shade300,
),
),
const SizedBox(width: 8,),
Text(feedData.userName)
],
),
const Icon(Icons.more_vert)
],
),
),
const SizedBox(height: 8,),
Container(
width: double.infinity,
height: 280,
color: Colors.indigo.shade300,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.favorite_outline)),
IconButton(onPressed: () {}, icon: const Icon(CupertinoIcons.chat_bubble)),
IconButton(onPressed: () {}, icon: const Icon(CupertinoIcons.paperplane)),
],
),
IconButton(onPressed: () {}, icon: const Icon(CupertinoIcons.bookmark)),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text('좋아요 ${feedData.likeCount}개', style: const TextStyle(fontWeight: FontWeight.bold),),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 4),
child: RichText(text: TextSpan(children: [
TextSpan(text: feedData.userName, style: TextStyle(fontWeight: FontWeight. bold)),
TextSpan(text: feedData.content)
],
style: TextStyle(color: Colors.black)
)),
),
const SizedBox(height: 8)
],
);
}
}
search_screen.dart
import 'package:flutter/material.dart';
class SearchScreen extends StatelessWidget {
const SearchScreen({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
SearchTextBar(),
SearchGrid(),
],
),
),
);
}
}
class SearchTextBar extends StatelessWidget {
const SearchTextBar({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 60,
child: Padding(
padding: const EdgeInsets.all(8),
child: TextField(
cursorColor: Colors.black,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
hintText: '검색',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(color: Colors.grey.shade200, width: 1)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(color: Colors.grey.shade200, width: 1)),
contentPadding: const EdgeInsets.all(0),
filled: true,
fillColor: Colors.grey.shade200),
),
),
);
}
}
final gridItems = List.generate(30, (index) => Colors.green.shade300);
class SearchGrid extends StatelessWidget {
const SearchGrid({super.key});
@override
Widget build(BuildContext context) {
return GridView.count(
padding: EdgeInsets.zero,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
crossAxisCount: 3,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: gridItems.map((color) => Container(color: color)).toList(),
);
}
}