こんにちは 皆さん!Dreamwalkerです。
メリークリスマス!
どんな年末過ごしているでしょうか
忙しくて、遅くなってしまいました。
今回は13番目の「DribbbleのデザインをFlutterでやってみた」になります。
今回のデザイン
https://dribbble.com/shots/9110398-Gift-Shop/attachments/1183035?mode=media
結果
一つ目のページ。
二つ目のページ。
必要なライブラリー
1.なし
全てのコード
main。
main.dart
import 'package:flutter/material.dart';
void main() => runApp(GiftShopApp());
MaterialApp Importer。
home_page.dart
import 'package:flutter/material.dart';
import '../gift_app/main_page.dart';
class GiftShopApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ShopMainPage(),
);
}
}
一つ目のページ。
ShopMainPage
BottomNavigationBarがあるので、IndexedStackを使ってインプリメントしてみました。
main_page.dart
import 'package:flutter/material.dart';
import '/gift_app/main_cart_page.dart';
import '/gift_app/main_home_page.dart';
class ShopMainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<ShopMainPage> {
int pageIndex = 0;
final _page = [
MainHomePage(),
MainCartPage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: pageIndex,
children: _page,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.black,
unselectedItemColor: Colors.grey,
onTap: (newValue) {
setState(() {
pageIndex = newValue;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.add_shopping_cart,
),
title: Text("Cart"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.archive,
),
title: Text("Archive"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.share,
),
title: Text("Share"),
)
],
),
);
}
}
Main Home Page Widget
main_home_page.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '/gift_app/dad_gift_card.dart';
import '/gift_app/filter_icon.dart';
import '/gift_app/moms_gift_card.dart';
import '/gift_app/top_menu_io.dart';
class MainHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://cdn.pixabay.com/photo/2019/12/14/20/03/christmas-balls-4695657_960_720.jpg"),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.6), BlendMode.darken)),
),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 7,
child: Center(
child: Text(
"Christmas Gifts",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 24,
),
),
),
),
Container(
padding: EdgeInsets.only(left: 24),
height: MediaQuery.of(context).size.height / 8,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
TopBarItem(
isSelected: true,
),
TopBarItem(
isSelected: false,
),
TopBarItem(
isSelected: false,
),
TopBarItem(
isSelected: false,
),
TopBarItem(
isSelected: false,
),
],
)),
Container(
padding: EdgeInsets.only(left: 24, top: 24),
height: MediaQuery.of(context).size.height / 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Mom Gifts",
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 8,
),
Padding(
padding: const EdgeInsets.only(right: 24),
child: Row(
children: <Widget>[
Text(
"Filters:",
style: TextStyle(
color: Colors.white,
fontSize: 22,
),
),
SizedBox(
width: 9,
),
Text(
"Soup; Cream; Cleanser;",
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
Spacer(),
FilterIcons(),
],
),
),
Container(
padding: EdgeInsets.only(top: 6),
height: MediaQuery.of(context).size.height / 2.7,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
MomsGiftCard(
title: "Soup",
price: "23.54",
imgPath: "https://cdn.pixabay.com/photo/2016/02/19/10/40/soap-1209344__340.jpg",
),
MomsGiftCard(
title: "Cleanser",
price: "43.90",
imgPath: "https://cdn.pixabay.com/photo/2016/02/19/10/40/soap-1209344__340.jpg",
),
MomsGiftCard(
title: "Shower?",
price: "99.99",
imgPath: "https://cdn.pixabay.com/photo/2016/02/19/10/40/soap-1209344__340.jpg",
),
],
))
],
)),
Container(
padding: EdgeInsets.only(left: 24, top: 24),
height: MediaQuery.of(context).size.height / 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Dad Gifts",
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 8,
),
Padding(
padding: const EdgeInsets.only(right: 24),
child: Row(
children: <Widget>[
Text(
"Filters:",
style: TextStyle(
color: Colors.white,
fontSize: 22,
),
),
SizedBox(
width: 9,
),
Text(
"Sweater; Hoodie; Gel; Hat;",
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
Spacer(),
FilterIcons(),
],
),
),
Container(
padding: EdgeInsets.only(top: 6),
height: MediaQuery.of(context).size.height / 2.7,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
DadGiftCard(
title: "Sweater",
price: "23.54",
imgPath: "https://cdn.pixabay.com/photo/2016/03/27/19/31/fashion-1283863__340.jpg",
),
DadGiftCard(
title: "Hoodie",
price: "43.90",
imgPath: "https://cdn.pixabay.com/photo/2015/03/26/10/10/surfer-691031__340.jpg",
),
DadGiftCard(
title: "Gel",
price: "99.99",
imgPath: "https://cdn.pixabay.com/photo/2016/03/27/19/31/fashion-1283863__340.jpg",
),
],
))
],
)),
],
),
),
),
)
],
);
}
}
二つ目のページ。
Product Detail Page
ユーザーから選択してもらうデータをDetailsページにあげます。
StatefulWidgetをして作りましたが、
状態管理が必要ないならStatelessWidgetにしても問題ないです。
product_detail_page.dart
import 'package:flutter/material.dart';
import '/gift_app/dad_gift_card.dart';
class ProductDetailPage extends StatefulWidget {
final String title;
final String product;
final String price;
final String imgPath;
ProductDetailPage({this.title, this.product, this.price, this.imgPath});
@override
_ProductDetailPageState createState() => _ProductDetailPageState();
}
class _ProductDetailPageState extends State<ProductDetailPage> {
int pageIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://cdn.pixabay.com/photo/2019/12/16/07/41/winter-4698763__340.jpg",
),
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.65),
BlendMode.darken,
),
fit: BoxFit.cover,
)),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
top: 32,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 8,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
widget.title,
style: TextStyle(color: Colors.grey),
),
Padding(
padding: const EdgeInsets.only(right: 48),
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
color: Colors.white,
onPressed: () {
Navigator.of(context).pop();
},
),
Spacer(),
Text(
"Gel Description",
style: TextStyle(
color: Colors.white,
fontSize: 21,
fontWeight: FontWeight.w700),
),
Spacer()
],
),
)
],
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 24),
height: MediaQuery.of(context).size.height / 2.7,
child: Column(
children: <Widget>[
Expanded(
flex: 10,
child: Row(
children: <Widget>[
Expanded(
flex: 4,
child: Container(
margin:
EdgeInsets.only(right: 12, bottom: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
image: DecorationImage(
image: NetworkImage(widget.imgPath),
fit: BoxFit.cover,
)),
),
),
Expanded(
flex: 5,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Honest Beauty",
style: TextStyle(
color: Colors.white, fontSize: 16),
),
SizedBox(
height: 8,
),
Text(
widget.product,
style: TextStyle(
color: Colors.white, fontSize: 20),
),
SizedBox(
height: 16,
),
Padding(
padding: const EdgeInsets.only(right: 16),
child: Text(
"A unique cleansing gel that removes impurities and unclogs pores for a brighter skin appearance",
style: TextStyle(
color:
Colors.white.withOpacity(0.8),
letterSpacing: 1.5,
fontWeight: FontWeight.w300,
fontSize: 13,
wordSpacing: 1),
),
),
Spacer(),
Padding(
padding:
const EdgeInsets.only(bottom: 16),
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
height: 38,
margin:
EdgeInsets.only(right: 16),
padding: EdgeInsets.all(3),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(12),
border: Border.all(
color: Colors.white,
)),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(
8)),
padding: EdgeInsets.all(4),
child: Row(
children: <Widget>[
Text(
"QTY",
style: TextStyle(
color: Colors.black,
fontWeight:
FontWeight.bold,
),
),
Spacer(),
Text(
"1",
style: TextStyle(
color: Colors.black,
fontWeight:
FontWeight.bold,
),
),
Icon(
Icons.keyboard_arrow_down,
size: 14,
)
],
),
),
),
),
Expanded(
flex: 1,
child: Container(
height: 38,
margin:
EdgeInsets.only(right: 16),
padding: EdgeInsets.all(3),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(12),
border: Border.all(
color: Colors.white,
)),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(
8)),
padding: EdgeInsets.all(4),
child: Center(
child: Text(
"Wish List",
style: TextStyle(
fontWeight:
FontWeight.bold),
),
)),
),
),
],
),
)
],
),
),
],
),
),
Expanded(
flex: 3,
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16)),
child: Center(
child: Text(
"Purchase for \$${widget.price}",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
),
),
),
],
),
),
Container(
padding: EdgeInsets.only(left: 24, top: 8),
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
"Compatible with:",
style: TextStyle(color: Colors.white, fontSize: 22),
),
Container(
height: MediaQuery.of(context).size.height / 3,
margin: EdgeInsets.only(top: 8),
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
DadGiftCard(
title: "Towel",
price: "11.45",
imgPath:
"https://cdn.pixabay.com/photo/2018/01/07/04/21/lavender-3066531__340.jpg",
),
DadGiftCard(
title: "Cream",
price: "68.80",
imgPath:
"https://cdn.pixabay.com/photo/2018/06/25/13/00/cream-3496778__340.jpg",
),
DadGiftCard(
title: "Balm",
price: "11.45",
imgPath:
"https://cdn.pixabay.com/photo/2018/01/07/04/21/lavender-3066531__340.jpg",
),
],
),
)
],
),
)
],
),
),
)
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.black,
unselectedItemColor: Colors.grey,
onTap: (newValue) {
setState(() {
pageIndex = newValue;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.add_shopping_cart,
),
title: Text("Cart"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.archive,
),
title: Text("Archive"),
),
BottomNavigationBarItem(
icon: Icon(
Icons.share,
),
title: Text("Share"),
)
],
),
);
}
}
終わりに
今回も読んでくださってありがとうございます。