main.dart
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:plant/constants.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: kPrimaryColor,
textTheme: Theme.of(context).textTheme.apply(bodyColor: kTextColor),
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
elevation: 0,
leading: IconButton(
icon: SvgPicture.asset('assets/icons/menu.svg'), onPressed: null),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: size.height * 0.2,
child: Stack(
children: [
Container(
padding: EdgeInsets.only(
left: kDefaultPadding,
right: kDefaultPadding,
bottom: 36 + kDefaultPadding),
height: size.height * 0.2 - 27,
decoration: BoxDecoration(
color: kPrimaryColor,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(36),
bottomRight: Radius.circular(36))),
child: Row(
children: [
Text(
'Hi Miles',
style: Theme.of(context).textTheme.headline5.copyWith(
color: Colors.white, fontWeight: FontWeight.bold),
),
Spacer(),
Image.asset("assets/images/logo.png")
],
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
margin:
EdgeInsets.symmetric(horizontal: kDefaultPadding),
padding:
EdgeInsets.symmetric(horizontal: kDefaultPadding),
height: 54,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
blurRadius: 50,
color: kPrimaryColor.withOpacity(0.23))
]),
child: Row(
children: [
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: 'Search',
hintStyle: TextStyle(
color: kPrimaryColor.withOpacity(0.5)),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none),
),
),
SvgPicture.asset("assets/icons/search.svg")
],
),
))
],
),
),
TitleWithMoreButton(
title: 'Recomended',
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
RecomendPlantCard(
size: size,
image: "assets/images/image_1.png",
title: 'Samantha\n'.toUpperCase(),
price: 88,
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage()));
},
),
RecomendPlantCard(
size: size,
image: "assets/images/image_2.png",
title: 'Samantha\n'.toUpperCase(),
price: 88,
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage()));
},
),
RecomendPlantCard(
size: size,
image: "assets/images/image_3.png",
title: 'Samantha\n'.toUpperCase(),
price: 88,
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage()));
},
),
],
),
),
TitleWithMoreButton(
title: 'Featured Plants',
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
margin: EdgeInsets.only(
left: kDefaultPadding,
top: kDefaultPadding / 2,
bottom: kDefaultPadding / 2),
width: size.width * 0.8,
height: 185,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage("assets/images/bottom_img_1.png"),
fit: BoxFit.cover)),
),
Container(
margin: EdgeInsets.only(
left: kDefaultPadding,
top: kDefaultPadding / 2,
bottom: kDefaultPadding / 2),
width: size.width * 0.8,
height: 185,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage("assets/images/bottom_img_2.png"),
fit: BoxFit.cover)),
),
],
),
)
],
),
),
bottomNavigationBar: MyBottomNavigationBar(),
);
}
}
class MyBottomNavigationBar extends StatelessWidget {
const MyBottomNavigationBar({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(
left: kDefaultPadding * 2,
right: kDefaultPadding * 2,
bottom: kDefaultPadding - 15),
height: 60,
decoration: BoxDecoration(color: Colors.white, boxShadow: [
BoxShadow(
offset: Offset(0, -10),
blurRadius: 35,
color: kPrimaryColor.withOpacity(0.38))
]),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: SvgPicture.asset("assets/icons/flower.svg"),
onPressed: () {}),
IconButton(
icon: SvgPicture.asset("assets/icons/heart-icon.svg"),
onPressed: () {}),
IconButton(
icon: SvgPicture.asset("assets/icons/user-icon.svg"),
onPressed: () {})
],
),
);
}
}
class TitleWithMoreButton extends StatelessWidget {
const TitleWithMoreButton({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Container(
height: 100,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding),
child: Row(
children: [
Stack(
children: [
Padding(
padding: EdgeInsets.only(left: kDefaultPadding / 4, top: 15),
child: Text(
this.title,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
Positioned(
bottom: 0,
left: 8,
right: 0,
child: Container(
margin: EdgeInsets.only(right: kDefaultPadding / 4),
height: 5,
color: kPrimaryColor.withOpacity(0.2),
))
],
),
Spacer(),
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: kPrimaryColor,
onPressed: () {},
child: Text(
'More',
style: TextStyle(color: Colors.white),
),
)
],
),
),
);
}
}
class RecomendPlantCard extends StatelessWidget {
const RecomendPlantCard({
Key key,
@required this.size,
this.image,
this.title,
this.price,
this.press,
}) : super(key: key);
final Size size;
final String image;
final String title;
final double price;
final press;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: press,
child: Container(
margin: EdgeInsets.only(
left: kDefaultPadding,
top: kDefaultPadding / 2,
bottom: kDefaultPadding * 2.5),
width: size.width * 0.4,
child: Column(
children: [
Image.asset(this.image),
Container(
padding: EdgeInsets.all(kDefaultPadding / 2),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
blurRadius: 50,
color: kPrimaryColor.withOpacity(0.23)),
],
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10))),
child: Row(
children: [
RichText(
text: TextSpan(children: [
TextSpan(
text: this.title,
style: Theme.of(context).textTheme.button),
TextSpan(
text: 'Russia'.toUpperCase(),
style:
TextStyle(color: kPrimaryColor.withOpacity(0.5))),
])),
Spacer(),
Text(
'\$' + this.price.toString(),
style: Theme.of(context)
.textTheme
.button
.copyWith(color: kPrimaryColor),
)
],
),
)
],
),
),
);
}
}
class DetailsPage extends StatefulWidget {
DetailsPage({Key key}) : super(key: key);
@override
_DetailsPageState createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
ImageAndIcons(size: size),
TitleAndPrice(
title: "Angelica",
country: "Russia",
price: 500,
),
SizedBox(height: kDefaultPadding),
Row(
children: [
SizedBox(
width: size.width / 2,
height: 84,
child: FlatButton(
color: kPrimaryColor,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.only(topRight: Radius.circular(20))),
onPressed: () {},
child: Text(
"Buy Now",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {},
child: Text(
'Description',
style: TextStyle(fontSize: 20, color: kPrimaryColor),
),
))
],
)
],
),
),
);
}
}
class TitleAndPrice extends StatelessWidget {
const TitleAndPrice({
Key key,
this.title,
this.country,
this.price,
}) : super(key: key);
final String title, country;
final int price;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: kDefaultPadding),
child: Row(
children: [
RichText(
text: TextSpan(children: [
TextSpan(
text: title + "\n",
style: Theme.of(context).textTheme.headline4.copyWith(
color: kTextColor, fontWeight: FontWeight.bold)),
TextSpan(
text: country,
style: TextStyle(
fontSize: 20,
color: kPrimaryColor,
fontWeight: FontWeight.w300))
])),
Spacer(),
Text("\$" + price.toString(),
style: Theme.of(context)
.textTheme
.headline5
.copyWith(color: kPrimaryColor))
],
));
}
}
class ImageAndIcons extends StatelessWidget {
const ImageAndIcons({
Key key,
@required this.size,
}) : super(key: key);
final Size size;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: kDefaultPadding * 3),
child: SizedBox(
height: size.height * 0.8,
child: Row(
children: [
Expanded(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: kDefaultPadding * 3),
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: IconButton(
padding:
EdgeInsets.symmetric(horizontal: kDefaultPadding),
icon: SvgPicture.asset("assets/icons/back_arrow.svg"),
onPressed: () {
Navigator.pop(context);
},
),
),
Spacer(),
IconCard(icon: "assets/icons/sun.svg"),
IconCard(icon: "assets/icons/icon_2.svg"),
IconCard(icon: "assets/icons/icon_3.svg"),
IconCard(icon: "assets/icons/icon_4.svg")
],
),
)),
Container(
height: size.height * 0.8,
width: size.width * 0.75,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(63),
bottomLeft: Radius.circular(63)),
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
blurRadius: 60,
color: kPrimaryColor.withOpacity(0.3))
],
image: DecorationImage(
fit: BoxFit.cover,
alignment: Alignment.centerLeft,
image: AssetImage("assets/images/img.png"))),
)
],
),
),
);
}
}
class IconCard extends StatelessWidget {
const IconCard({
Key key,
this.icon,
}) : super(key: key);
final String icon;
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
margin: EdgeInsets.symmetric(vertical: size.height * 0.03),
height: 45,
width: 45,
decoration: BoxDecoration(
color: kBackgroundColor,
borderRadius: BorderRadius.circular(6),
boxShadow: [
BoxShadow(
offset: Offset(0, 15),
blurRadius: 22,
color: kPrimaryColor.withOpacity(0.22)),
BoxShadow(
offset: Offset(-15, -15), blurRadius: 20, color: Colors.white),
]),
child: SvgPicture.asset(icon),
);
}
}
constants.dart
import 'package:flutter/material.dart';
// Colors that we use in our app
const kPrimaryColor = Color(0xFF0C9869);
const kTextColor = Color(0xFF3C4046);
const kBackgroundColor = Color(0xFFF9F8FD);
const double kDefaultPadding = 20.0;
name: plant
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_svg: ^0.18.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/icons/
- assets/images/
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
网友评论