Skip to content

Instantly share code, notes, and snippets.

@phanatagama
Last active September 14, 2023 15:07
Show Gist options
  • Save phanatagama/65c4a6e29ed171c4e05d0f8abaa64d39 to your computer and use it in GitHub Desktop.
Save phanatagama/65c4a6e29ed171c4e05d0f8abaa64d39 to your computer and use it in GitHub Desktop.
Stack Widget
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
//Add this CustomPaint widget to the Widget Tree
const primaryColor = Color(0xFF40128B);
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(home: MyPage());
}
class MyPage extends StatefulWidget {
@override
MyPageState createState() => MyPageState();
}
class MyPageState extends State<MyPage> with WidgetsBindingObserver {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: _buildColumn(),
),
);
}
Widget _buildColumn() => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// First blue container
_buildTopContainer(),
// Button with offset
// _buildMidContainerWithButton(),
_buildMidC(),
// Bottom white container
_buildBottomContainer(),
],
);
Widget _buildTopContainer() => Stack(
// flex: 2,
// fit: StackFit.expand,
children: [
ClipPath(
clipper: ArcClipper(),
child: Container(
color: primaryColor,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(children: [
const Text('OVO',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w600)),
const Spacer(),
IconButton(
icon: const Icon(
Icons.notification_add,
color: Colors.white,
),
tooltip: 'Increase volume by 10',
onPressed: () {},
),
]),
Text(
'OVO Cash',
style: TextStyle(color: Colors.white, fontSize: 16),
),
RichText(
text: TextSpan(
style: TextStyle(color: Colors.white, fontSize: 16),
children: [
// TextSpan(text: 'Loh'),
WidgetSpan(
alignment: PlaceholderAlignment.top,
child: Text('Rp ',
style: TextStyle(
fontSize: 12, color: Colors.white)),
),
TextSpan(
text: '4.980.000',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 24)),
],
),
),
SizedBox(height: 100),
Text(
'Top container',
style: TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
],
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: ClipPath(
clipper: WaveClipper(),
child: Container(
color: Colors.white.withOpacity(0.1),
width: double.infinity,
height: 100,
),
),
),
]);
Widget _buildMidC() {
return Stack(
children: [
Container(
height: 100,
color: Colors.red,
child: const Center(
child: Text('First stack element'),
),
),
Transform.translate(
offset: const Offset(0.0, -100 / 2),
child: Center(
child: Container(
padding: const EdgeInsets.all(24.0),
margin: EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.blue[600],
borderRadius: BorderRadius.circular(32.0 / 2.0),
boxShadow: [
BoxShadow(
blurRadius: 16.0,
offset: const Offset(0.0, 6.0),
color: Colors.black.withOpacity(0.16),
),
],
),
child: const Wrap(
// mainAxisSize: MainAxisSize.min,
children: [
Column(
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Text('Jadwal Shalat'),
],
),
Column(
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Text('Jadwal Shalat'),
],
),
Column(
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Text('Jadwal Shalat'),
],
),
Column(
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Text('Jadwal Shalat'),
],
),
Column(
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Text('Jadwal Shalat'),
],
),
],
),
),
),
),
],
);
}
Widget buildMidContainerWithButton() {
const buttonHeight = 50.0;
return Stack(
children: [
// Use same background color like the second container
//Container(height: 5, color: Colors.red),
// Translate the button
Transform.translate(
offset: const Offset(0.0, -buttonHeight / 2.0),
child: Center(
child: GestureDetector(
onTap: () {/* do stuff */},
child: Container(
height: buttonHeight,
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(buttonHeight / 2.0),
boxShadow: [
BoxShadow(
blurRadius: 16.0,
offset: const Offset(0.0, 6.0),
color: Colors.black.withOpacity(0.16),
),
],
),
padding: const EdgeInsets.fromLTRB(24.0, 3.0, 24.0, 0.0),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.photo_camera_outlined,
size: 20.0,
color: Colors.white,
),
Padding(
padding: EdgeInsets.only(left: 8.0),
child: Text(
'Use camera',
style: TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
],
),
),
),
),
),
],
);
}
Widget _buildBottomContainer() => Flexible(
flex: 8,
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CustomPaint(
size: const Size(22, 27),
painter: RPSCustomPainter(),
),
const Text(
'Bottom container',
style: TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: Colors.black54,
),
),
]),
),
);
}
class WaveClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, size.height - 30);
// path.lineTo(size.width, size.height);
var firstControlPoint = Offset(size.width / 4, size.height);
var firstPoint = Offset(size.width / 2, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
var secondControlPoint = Offset(size.width - (size.width / 4), size.height);
var secondPoint = Offset(size.width, size.height - 30);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
// path.quadraticBezierTo(size.width/3, size.height, size.width/2, size.height);
// path.quadraticBezierTo(size.width - (size.width/3), size.height, size.width, size.height-(size.height/3));
path.lineTo(size.width, 10);
path.quadraticBezierTo(
size.width - 50, size.height / 5, size.width - 100, size.height / 10);
path.quadraticBezierTo((size.width / 2) + 30, 0, size.width / 2, 30);
path.quadraticBezierTo((size.width / 4) + 30, 60, size.width / 6, 30);
path.quadraticBezierTo(size.width / 8, 10, 0, 30);
// path.quadraticBezierTo(size.width/4, size.height/2, size.width/5, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
class ArcClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height - 30);
var firstControlPoint = Offset(size.width / 4, size.height);
var firstPoint = Offset(size.width / 2, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
var secondControlPoint = Offset(size.width - (size.width / 4), size.height);
var secondPoint = Offset(size.width, size.height - 30);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
//Copy this CustomPainter code to the Bottom of the File
class RPSCustomPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Path path_0 = Path();
path_0.moveTo(10.9997, 13.5001);
path_0.cubicTo(9.53301, 13.5001, 8.33301, 12.3001, 8.33301, 10.8334);
path_0.cubicTo(8.33301, 9.36675, 9.53301, 8.16675, 10.9997, 8.16675);
path_0.cubicTo(12.4663, 8.16675, 13.6663, 9.36675, 13.6663, 10.8334);
path_0.cubicTo(13.6663, 12.3001, 12.4663, 13.5001, 10.9997, 13.5001);
path_0.close();
path_0.moveTo(18.9997, 11.1001);
path_0.cubicTo(18.9997, 6.26008, 15.4663, 2.83341, 10.9997, 2.83341);
path_0.cubicTo(6.53301, 2.83341, 2.99967, 6.26008, 2.99967, 11.1001);
path_0.cubicTo(2.99967, 14.2201, 5.59967, 18.3534, 10.9997, 23.2867);
path_0.cubicTo(16.3997, 18.3534, 18.9997, 14.2201, 18.9997, 11.1001);
path_0.close();
path_0.moveTo(10.9997, 0.166748);
path_0.cubicTo(16.5997, 0.166748, 21.6663, 4.46008, 21.6663, 11.1001);
path_0.cubicTo(21.6663, 15.5267, 18.1063, 20.7667, 10.9997, 26.8334);
path_0.cubicTo(3.89301, 20.7667, 0.333008, 15.5267, 0.333008, 11.1001);
path_0.cubicTo(0.333008, 4.46008, 5.39967, 0.166748, 10.9997, 0.166748);
path_0.close();
Paint paint_0_fill = Paint()..style = PaintingStyle.fill;
paint_0_fill.color = Color(0xff28C76F).withOpacity(1.0);
canvas.drawPath(path_0, paint_0_fill);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment