Tutorial Flutter — Membuat Tampilan Instagram
Tutorial Flutter Bahasa Indonesia — Membuat Tampilan Instagram
Halo semua, kembali lagi dengan saya Alfi. Pada tutorial kali ini kita akan membahas cara membuat tampilan Instagram dengan Flutter.
Sebelumnya perlu teman-teman ketahui disini saya hanya akan menggunakan data static alias tidak terkoneksi dengan data manapun, kalo gitu yuk kita mulai.
Pertama, setup pubspec.yaml File
Pertama kita akan membuka assets untuk menaru gambar yang ingin kita tampilkan dan menambahkan design huruf yang sama seperti aplikasi instagram .
Kedua, Tambahkan Font
Silahkan download font yang ingin kita tambahkan, download disini dan copy ke bagian assets.
Ketiga, membuat screen untuk post dan feed.
Kali ini kita akan membuat screen untuk membuat UI seperti tampilan instagram, Sekarang kita buat sebuah file bernama post_screen.dart didalam folder screens, lalu paste codenya dibawah ini.
import 'package:flutter/material.dart';
import 'package:flutter_instagram_feed_ui_redesign/models/comment.dart';
import 'package:flutter_instagram_feed_ui_redesign/models/model.dart';
class ViewPostScreen extends StatefulWidget {
final Post post;
ViewPostScreen({this.post});
@override
_ViewPostScreenState createState() => _ViewPostScreenState();
}
class _ViewPostScreenState extends State<ViewPostScreen> {
Widget _buildComment(int index) {
return Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
leading: Container(
width: 50.0,
height: 50.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 2),
blurRadius: 6.0,
),
],
),
child: CircleAvatar(
child: ClipOval(
child: Image(
height: 50.0,
width: 50.0,
image: AssetImage(comments[index].authorImageUrl),
fit: BoxFit.cover,
),
),
),
),
title: Text(
comments[index].authorName,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(comments[index].text),
trailing: IconButton(
icon: Icon(
Icons.favorite_border,
),
color: Colors.grey,
onPressed: () => print('Like comment'),
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFEDF0F6),
body: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 40.0),
width: double.infinity,
height: 600.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25.0),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
iconSize: 30.0,
color: Colors.black,
onPressed: () => Navigator.pop(context),
),
Container(
width: MediaQuery.of(context).size.width * 0.8,
child: ListTile(
leading: Container(
width: 50.0,
height: 50.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 2),
blurRadius: 6.0,
),
],
),
child: CircleAvatar(
child: ClipOval(
child: Image(
height: 50.0,
width: 50.0,
image: AssetImage(
widget.post.authorImageUrl),
fit: BoxFit.cover,
),
),
),
),
title: Text(
widget.post.authorName,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(widget.post.timeAgo),
trailing: IconButton(
icon: Icon(Icons.more_horiz),
color: Colors.black,
onPressed: () => print('More'),
),
),
),
],
),
InkWell(
onDoubleTap: () => print('Like post'),
child: Container(
margin: EdgeInsets.all(10.0),
width: double.infinity,
height: 400.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 5),
blurRadius: 8.0,
),
],
image: DecorationImage(
image: AssetImage(widget.post.imageUrl),
fit: BoxFit.fitWidth,
),
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.favorite_border),
iconSize: 30.0,
onPressed: () => print('Like post'),
),
Text(
'1000',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(width: 20.0),
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.chat),
iconSize: 30.0,
onPressed: () {
print('Chat');
},
),
Text(
'100',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
IconButton(
icon: Icon(Icons.bookmark_border),
iconSize: 30.0,
onPressed: () => print('Save post'),
),
],
),
),
],
),
),
],
),
),
SizedBox(height: 10.0),
Container(
width: double.infinity,
height: 600.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Column(
children: <Widget>[
_buildComment(0),
_buildComment(1),
_buildComment(2),
_buildComment(3),
_buildComment(4),
],
),
)
],
),
),
bottomNavigationBar: Transform.translate(
offset: Offset(0.0, -1 * MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0, -2),
blurRadius: 6.0,
),
],
color: Colors.white,
),
child: Padding(
padding: EdgeInsets.all(12.0),
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Colors.grey),
),
contentPadding: EdgeInsets.all(20.0),
hintText: 'Add a comment',
prefixIcon: Container(
margin: EdgeInsets.all(4.0),
width: 48.0,
height: 48.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 2),
blurRadius: 6.0,
),
],
),
child: CircleAvatar(
child: ClipOval(
child: Image(
height: 48.0,
width: 48.0,
image: AssetImage(widget.post.authorImageUrl),
fit: BoxFit.cover,
),
),
),
),
suffixIcon: Container(
margin: EdgeInsets.only(right: 4.0),
width: 70.0,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Color(0xFF23B66F),
onPressed: () => print('Post comment'),
child: Icon(
Icons.send,
size: 25.0,
color: Colors.white,
),
),
),
),
),
),
),
),
);
}
}
Masih di folder yang sama kita akan membuat feed_screen.dart seperti di bawah ini.
import 'package:flutter/material.dart';
import 'package:flutter_instagram_feed_ui_redesign/models/model.dart';
import 'package:flutter_instagram_feed_ui_redesign/screens/post_screen.dart';
class FeedScreen extends StatefulWidget {
@override
_FeedScreenState createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
Widget _buildPost(int index) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Container(
width: double.infinity,
height: 560.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25.0),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Column(
children: <Widget>[
ListTile(
leading: Container(
width: 50.0,
height: 50.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 2),
blurRadius: 6.0,
),
],
),
child: CircleAvatar(
child: ClipOval(
child: Image(
height: 50.0,
width: 50.0,
image: AssetImage(posts[index].authorImageUrl),
fit: BoxFit.cover,
),
),
),
),
title: Text(
posts[index].authorName,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(posts[index].timeAgo),
trailing: IconButton(
icon: Icon(Icons.more_horiz),
color: Colors.black,
onPressed: () => print('More'),
),
),
InkWell(
onDoubleTap: () => print('Like post'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ViewPostScreen(
post: posts[index],
),
),
);
},
child: Container(
margin: EdgeInsets.all(10.0),
width: double.infinity,
height: 400.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 5),
blurRadius: 8.0,
),
],
image: DecorationImage(
image: AssetImage(posts[index].imageUrl),
fit: BoxFit.fitWidth,
),
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.favorite_border),
iconSize: 30.0,
onPressed: () => print('Like post'),
),
Text(
'1,000',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(width: 20.0),
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.chat),
iconSize: 30.0,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ViewPostScreen(
post: posts[index],
),
),
);
},
),
Text(
'100',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
IconButton(
icon: Icon(Icons.bookmark_border),
iconSize: 30.0,
onPressed: () => print('Save post'),
),
],
),
),
],
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFEDF0F6),
body: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Instagram',
style: TextStyle(
fontFamily: 'Billabong',
fontSize: 32.0,
),
),
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.live_tv),
iconSize: 30.0,
onPressed: () => print('IGTV'),
),
SizedBox(width: 16.0),
Container(
width: 35.0,
child: IconButton(
icon: Icon(Icons.send),
iconSize: 30.0,
onPressed: () => print('Direct Messages'),
),
)
],
)
],
),
),
Container(
width: double.infinity,
height: 100.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: stories.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return SizedBox(width: 10.0);
}
return Container(
margin: EdgeInsets.all(10.0),
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 2),
blurRadius: 6.0,
),
],
),
child: CircleAvatar(
child: ClipOval(
child: Image(
height: 60.0,
width: 60.0,
image: AssetImage(stories[index - 1]),
fit: BoxFit.cover,
),
),
),
);
},
),
),
_buildPost(0),
_buildPost(1),
],
),
bottomNavigationBar: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.dashboard,
size: 30.0,
color: Colors.black,
),
title: Text(''),
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
size: 30.0,
color: Colors.grey,
),
title: Text(''),
),
BottomNavigationBarItem(
icon: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 10.0),
child: FlatButton(
padding: EdgeInsets.symmetric(vertical: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Color(0xFF23B66F),
onPressed: () => print('Upload photo'),
child: Icon(
Icons.add,
size: 35.0,
color: Colors.white,
),
),
),
title: Text(''),
),
BottomNavigationBarItem(
icon: Icon(
Icons.favorite_border,
size: 30.0,
color: Colors.grey,
),
title: Text(''),
),
BottomNavigationBarItem(
icon: Icon(
Icons.person_outline,
size: 30.0,
color: Colors.grey,
),
title: Text(''),
),
],
),
),
);
}
}
Keempat, membuat model.
Nah, setelah kita membuat Folder Screens kali ini kita akan membuat Folder Model untuk memasukan gambar dan design dari instagram flutter, pertama kita akan membuat Model.dart seperti di bawah ini.
Setelah membuat model yang terakhir kita akan membuat comment.dart sebagai model commentnya, jadi apabila kita klik gambar maka akan pindah ke halaman comment seperti di instagram, codingannya seperti dibawah ini:
Apabila telah selesai semua, maka hasilnya akan menjadi seperti ini:
Sekian dari saya untuk kali ini, bila ingin mengambil source code-nya bisa langsung kunjungi github saya di https://github.com/alfigest/Flutter-Instagram. Happy Coding~ ^^