Skip to content

Commit 62cbdac

Browse files
committed
Buat wave bottom navigation bar
1 parent efa9bf0 commit 62cbdac

File tree

6 files changed

+267
-105
lines changed

6 files changed

+267
-105
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import 'package:flutter/material.dart';
2+
3+
class WavyBottomNavigationBarClipper extends CustomClipper<Path> {
4+
@override
5+
Path getClip(Size size) {
6+
Path path = Path();
7+
8+
path.lineTo(0, 2);
9+
path.lineTo(10, 3);
10+
path.lineTo(15, 5);
11+
path.lineTo(20, 10);
12+
var firstControlPoint = Offset((size.width / 3.6) - 40, 60);
13+
var firstEndPoint = Offset(size.width / 3.6, 10);
14+
path.quadraticBezierTo(
15+
firstControlPoint.dx,
16+
firstControlPoint.dy,
17+
firstEndPoint.dx,
18+
firstEndPoint.dy,
19+
);
20+
path.lineTo(size.width / 3.6, 10);
21+
22+
var dxSecondEndPoint = size.width / 3;
23+
var secondControlPoint = Offset(dxSecondEndPoint + 5, -10);
24+
var secondEndPoint = Offset(dxSecondEndPoint + 25, 10);
25+
path.quadraticBezierTo(
26+
secondControlPoint.dx,
27+
secondControlPoint.dy,
28+
secondEndPoint.dx,
29+
secondEndPoint.dy,
30+
);
31+
path.lineTo(dxSecondEndPoint + 25, 10);
32+
33+
var dxThirdEndPoint = size.width - (size.width / 2.5);
34+
var thirdControlPoint = Offset(dxThirdEndPoint - 36, 60);
35+
var thirdEndPoint = Offset((size.width / 3) * 2 - 25, 10);
36+
path.quadraticBezierTo(
37+
thirdControlPoint.dx,
38+
thirdControlPoint.dy,
39+
thirdEndPoint.dx,
40+
thirdEndPoint.dy,
41+
);
42+
43+
var dxFourthEndPoint = (size.width / 3) * 2;
44+
var fourthControlPoint = Offset(dxFourthEndPoint + 5, -10);
45+
var fourthEndPoint = Offset(dxFourthEndPoint + 25, 10);
46+
path.quadraticBezierTo(
47+
fourthControlPoint.dx,
48+
fourthControlPoint.dy,
49+
fourthEndPoint.dx,
50+
fourthEndPoint.dy,
51+
);
52+
53+
var dxFifthEndPoint = size.width - ((size.width / 3.6) - 40);
54+
var fifthControlPoint = Offset(dxFifthEndPoint, 60);
55+
var fifthEndPoint = Offset(dxFifthEndPoint + 40, 10);
56+
path.quadraticBezierTo(
57+
fifthControlPoint.dx,
58+
fifthControlPoint.dy,
59+
fifthEndPoint.dx,
60+
fifthEndPoint.dy,
61+
);
62+
63+
path.lineTo(size.width - 20, 10);
64+
path.lineTo(size.width - 15, 5);
65+
path.lineTo(size.width - 10, 3);
66+
path.lineTo(size.width, 2);
67+
path.lineTo(size.width, size.height);
68+
path.lineTo(0, size.height);
69+
path.close();
70+
71+
return path;
72+
}
73+
74+
@override
75+
bool shouldReclip(CustomClipper<Path> oldClipper) {
76+
return true;
77+
}
78+
}

lib/clipper/wavy_image_clipper.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'package:flutter/material.dart';
2+
3+
class WavyImageClipper extends CustomClipper<Path> {
4+
@override
5+
Path getClip(Size size) {
6+
Path path = Path();
7+
8+
path.lineTo(0, size.height - 200);
9+
var firstControlPoint = Offset(0, size.height - 160);
10+
var firstEndPoint = Offset(30, size.height - 150);
11+
path.quadraticBezierTo(
12+
firstControlPoint.dx,
13+
firstControlPoint.dy,
14+
firstEndPoint.dx,
15+
firstEndPoint.dy,
16+
);
17+
18+
path.lineTo(size.width - 30, size.height - 50);
19+
var secondControlPoint = Offset(size.width, size.height - 40);
20+
var secondEndPoint = Offset(size.width, size.height);
21+
path.quadraticBezierTo(
22+
secondControlPoint.dx,
23+
secondControlPoint.dy,
24+
secondEndPoint.dx,
25+
secondEndPoint.dy,
26+
);
27+
28+
path.lineTo(size.width, 200);
29+
var thirdControlPoint = Offset(size.width, 140);
30+
var thirdEndPoint = Offset(size.width - 30, 150);
31+
path.quadraticBezierTo(
32+
thirdControlPoint.dx,
33+
thirdControlPoint.dy,
34+
thirdEndPoint.dx,
35+
thirdControlPoint.dy,
36+
);
37+
38+
path.lineTo(30, 50);
39+
var fourthControlPoint = Offset(0, 40);
40+
var fourthEndPoint = Offset(0, 0);
41+
path.quadraticBezierTo(
42+
fourthControlPoint.dx,
43+
fourthControlPoint.dy,
44+
fourthEndPoint.dx,
45+
fourthEndPoint.dy,
46+
);
47+
48+
path.close();
49+
return path;
50+
}
51+
52+
@override
53+
bool shouldReclip(CustomClipper<Path> oldClipper) {
54+
return true;
55+
}
56+
}

lib/main.dart

Lines changed: 68 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import 'dart:ui';
22

33
import 'package:flutter/material.dart';
4+
import 'package:flutter_meditation_app/wavy/wavy_bottom_navigation_bar.dart';
5+
import 'package:flutter_meditation_app/wavy/wavy_image.dart';
6+
import 'package:flutter_meditation_app/widgets/container_black.dart';
47
import 'package:flutter_screenutil/flutter_screenutil.dart';
58

69
void main() => runApp(MyApp());
@@ -20,8 +23,6 @@ class MyHomePage extends StatelessWidget {
2023
ScreenUtil.init(context);
2124
MediaQueryData mediaQueryData = MediaQuery.of(context);
2225
double heightScreen = mediaQueryData.size.height;
23-
double paddingTop = mediaQueryData.padding.top;
24-
double paddingBottom = mediaQueryData.padding.bottom;
2526
return Scaffold(
2627
body: Container(
2728
width: double.infinity,
@@ -63,6 +64,62 @@ class MyHomePage extends StatelessWidget {
6364
),
6465
),
6566
_buildWidgetColumnText(),
67+
Align(
68+
alignment: Alignment.bottomCenter,
69+
child: WavyBottomNavigationBar(),
70+
),
71+
Align(
72+
alignment: Alignment.bottomCenter,
73+
child: Padding(
74+
padding: EdgeInsets.only(bottom: 100.w),
75+
child: Row(
76+
mainAxisAlignment: MainAxisAlignment.spaceAround,
77+
children: <Widget>[
78+
Container(
79+
decoration: BoxDecoration(
80+
color: Colors.white.withOpacity(0.1),
81+
shape: BoxShape.circle,
82+
),
83+
width: 150.w,
84+
height: 150.w,
85+
child: Icon(
86+
Icons.bubble_chart,
87+
color: Colors.white.withOpacity(0.5),
88+
size: ScreenUtil().setWidth(96),
89+
),
90+
),
91+
Container(
92+
decoration: BoxDecoration(
93+
color: Colors.white,
94+
shape: BoxShape.circle,
95+
border: Border.all(
96+
color: Colors.grey[800],
97+
width: 2,
98+
),
99+
),
100+
width: 150.w,
101+
height: 150.w,
102+
child: Icon(
103+
Icons.image,
104+
color: Colors.grey[900],
105+
),
106+
),
107+
Container(
108+
decoration: BoxDecoration(
109+
color: Colors.white.withOpacity(0.1),
110+
shape: BoxShape.circle,
111+
),
112+
width: 150.w,
113+
height: 150.w,
114+
child: Icon(
115+
Icons.brightness_3,
116+
color: Colors.white.withOpacity(0.5),
117+
),
118+
),
119+
],
120+
),
121+
),
122+
),
66123
],
67124
),
68125
),
@@ -92,12 +149,15 @@ class MyHomePage extends StatelessWidget {
92149
),
93150
),
94151
Expanded(
95-
child: Column(
96-
mainAxisAlignment: MainAxisAlignment.center,
97-
children: <Widget>[
98-
_buildWidgetTitle('Calm'),
99-
_buildWidgetSubtitle('Slow down and relax'),
100-
],
152+
child: Padding(
153+
padding: EdgeInsets.only(bottom: 200.w),
154+
child: Column(
155+
mainAxisAlignment: MainAxisAlignment.center,
156+
children: <Widget>[
157+
_buildWidgetTitle('Calm'),
158+
_buildWidgetSubtitle('Slow down and relax'),
159+
],
160+
),
101161
),
102162
),
103163
],
@@ -128,100 +188,3 @@ class MyHomePage extends StatelessWidget {
128188
);
129189
}
130190
}
131-
132-
class WavyImage extends StatelessWidget {
133-
final String img;
134-
135-
WavyImage(this.img);
136-
137-
@override
138-
Widget build(BuildContext context) {
139-
return ClipPath(
140-
child: Stack(
141-
children: <Widget>[
142-
Image.asset(
143-
img,
144-
fit: BoxFit.cover,
145-
height: 1150.w,
146-
),
147-
ContainerBlack(
148-
heightScreen: 1150.w,
149-
),
150-
],
151-
),
152-
clipper: WaveClipper(),
153-
);
154-
}
155-
}
156-
157-
class WaveClipper extends CustomClipper<Path> {
158-
@override
159-
Path getClip(Size size) {
160-
Path path = Path();
161-
162-
path.lineTo(0, size.height - 200);
163-
var firstControlPoint = Offset(0, size.height - 160);
164-
var firstEndPoint = Offset(30, size.height - 150);
165-
path.quadraticBezierTo(
166-
firstControlPoint.dx,
167-
firstControlPoint.dy,
168-
firstEndPoint.dx,
169-
firstEndPoint.dy,
170-
);
171-
172-
path.lineTo(size.width - 30, size.height - 50);
173-
var secondControlPoint = Offset(size.width, size.height - 40);
174-
var secondEndPoint = Offset(size.width, size.height);
175-
path.quadraticBezierTo(
176-
secondControlPoint.dx,
177-
secondControlPoint.dy,
178-
secondEndPoint.dx,
179-
secondEndPoint.dy,
180-
);
181-
182-
path.lineTo(size.width, 200);
183-
var thirdControlPoint = Offset(size.width, 140);
184-
var thirdEndPoint = Offset(size.width - 30, 150);
185-
path.quadraticBezierTo(
186-
thirdControlPoint.dx,
187-
thirdControlPoint.dy,
188-
thirdEndPoint.dx,
189-
thirdControlPoint.dy,
190-
);
191-
192-
path.lineTo(30, 50);
193-
var fourthControlPoint = Offset(0, 40);
194-
var fourthEndPoint = Offset(0, 0);
195-
path.quadraticBezierTo(
196-
fourthControlPoint.dx,
197-
fourthControlPoint.dy,
198-
fourthEndPoint.dx,
199-
fourthEndPoint.dy,
200-
);
201-
202-
path.close();
203-
return path;
204-
}
205-
206-
@override
207-
bool shouldReclip(CustomClipper<Path> oldClipper) {
208-
return true;
209-
}
210-
}
211-
212-
class ContainerBlack extends StatelessWidget {
213-
const ContainerBlack({
214-
Key key,
215-
@required this.heightScreen,
216-
}) : super(key: key);
217-
218-
final double heightScreen;
219-
220-
@override
221-
Widget build(BuildContext context) {
222-
return Container(
223-
height: heightScreen,
224-
color: Colors.black.withOpacity(0.5),
225-
);
226-
}
227-
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_meditation_app/clipper/wavy_bottom_navigation_bar_clipper.dart';
3+
import 'package:flutter_screenutil/flutter_screenutil.dart';
4+
5+
class WavyBottomNavigationBar extends StatelessWidget {
6+
@override
7+
Widget build(BuildContext context) {
8+
ScreenUtil.init(context);
9+
return ClipPath(
10+
child: Container(
11+
color: Colors.white,
12+
height: 180.w,
13+
),
14+
clipper: WavyBottomNavigationBarClipper(),
15+
);
16+
}
17+
}

lib/wavy/wavy_image.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_meditation_app/clipper/wavy_image_clipper.dart';
3+
import 'package:flutter_meditation_app/widgets/container_black.dart';
4+
import 'package:flutter_screenutil/flutter_screenutil.dart';
5+
6+
class WavyImage extends StatelessWidget {
7+
final String img;
8+
9+
WavyImage(this.img);
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
ScreenUtil.init(context);
14+
return ClipPath(
15+
child: Stack(
16+
children: <Widget>[
17+
Image.asset(
18+
img,
19+
fit: BoxFit.cover,
20+
height: 1150.w,
21+
),
22+
ContainerBlack(
23+
heightScreen: 1150.w,
24+
),
25+
],
26+
),
27+
clipper: WavyImageClipper(),
28+
);
29+
}
30+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy