How to create a Sine Wave Clipper in Flutter? - flutter

I want to create a Custom Clipper like the image below.

Finally figured it out.
Clip Widget
ClipPath(
child: Container(
height: 8,
width: double.infinity,
color: Colors.white,
),
clipper: WaveClipper(),
),
Wave Clipper
class WaveClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, size.height);
var x = 0.0;
var numberOfWaves = 30;
var increment = size.width / numberOfWaves;
bool startFromTop = false;
while (x < size.width) {
if (startFromTop) {
path.lineTo(x, 0);
path.cubicTo(x + increment / 2, 0, x + increment / 2, size.height,
x + increment, size.height);
} else {
path.lineTo(x, size.height);
path.cubicTo(x + increment / 2, size.height, x + increment / 2, 0,
x + increment, 0);
}
x += increment;
startFromTop = !startFromTop;
}
path.lineTo(size.width, 0);
path.lineTo(0, 0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
widget.title,
style: TextStyle(color: Colors.white),
),
),
body: Padding(
padding: const EdgeInsets.all(30.0),
child: ClipPath(
child: Container(
width: MediaQuery.of(context).size.width,
height: 200,
color: Colors.grey,
),
clipper: CustomClipPath(),
),
),
);
}
}
class CustomClipPath extends CustomClipper<Path> {
Path getClip(Size size) {
var path = new Path();
path.lineTo(0.0, 40.0);
path.lineTo(0.0, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 40.0);
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
path.quadraticBezierTo(
size.width - (size.width / 16) - (i * size.width / 8),
0.0,
size.width - ((i + 1) * size.width / 8),
size.height - 160);
} else {
path.quadraticBezierTo(
size.width - (size.width / 16) - (i * size.width / 8),
size.height - 120,
size.width - ((i + 1) * size.width / 8),
size.height - 160);
}
}
path.lineTo(0.0, 40.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

Related

how to create cove of top of Container and add image inside of CustomPainter in flutter app

how to add image inside of CustomPainter and manage.
like this:
import 'package:flutter/material.dart';
import 'package:hallo/appbar.dart';
class product1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body:Stack(
children: [
Column(
children: [
CustomPaint(
size: Size.fromHeight(500),
painter: RPSCustomPainter(),
),
Container(
)
],
)
],
)
);
}
}
class RPSCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint0 = Paint()
..color = const Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1.0;
Path path0 = Path();
path0.moveTo(0,0);
path0.lineTo(0,size.height);
path0.quadraticBezierTo(size.width*0.1120000,size.height*0.7968571,size.width*0.3375000,size.height*0.8585714);
path0.cubicTo(size.width*0.5795625,size.height*0.9350714,size.width*0.8043750,size.height*1.0775000,size.width,size.height);
path0.quadraticBezierTo(size.width,size.height*0.7500000,size.width,0);
path0.lineTo(size.width*0.1252500,0);
path0.lineTo(0,0);
path0.close();
canvas.drawPath(path0, paint0);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
try this:
class HomeScreen extends StatelessWidget {
const HomeScreen({
super.key,
});
static const String route = "/homeScreen";
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height * 0.5,
child: Image.network(
"https://images.pexels.com/photos/14446269/pexels-photo-14446269.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
fit: BoxFit.cover,
width: double.infinity,
),
),
CustomPaint(
size: MediaQuery.of(context).size,
painter: RPSCustomPainter(),
),
],
),
);
}
}
class RPSCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint0 = Paint()
..color = const Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.fill
..strokeWidth = 5.0;
Path path1 = Path();
path1.moveTo(0, size.height);
path1.lineTo(0, size.height * 0.5);
path1.quadraticBezierTo(
size.width * 0.1120000,
size.height * 0.5 * 0.7968571,
size.width * 0.3375000,
size.height * 0.5 * 0.8585714);
path1.cubicTo(
size.width * 0.5795625,
size.height * 0.5 * 0.9350714,
size.width * 0.8043750,
size.height * 0.5 * 1.0775000,
size.width,
size.height * 0.5,
);
path1.lineTo(size.width, size.height);
path1.lineTo(0, size.height);
path1.close();
canvas.drawPath(path1, paint0);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
you will get this type of results:

Shaping Container using Bezier Curve in Flutter

Up to this point, I wasn't aware that we could make shapes of our choices in Flutter and hence I'm totally new to this. I would like to shape my container to resemble the below design but I am totally short of ideas as to how this can be done. I did a bit of reading to find out about the concepts of the Bezier Curve but upon trying to apply that knowledge to the container below, I ended up getting something pretty horrendous. The screenshots and the code are as follows:
This is what I ended up getting:
class ProfilePage extends StatefulWidget {
ProfilePageState createState() => ProfilePageState();
}
class ProfilePageState extends State<ProfilePage> {
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
// TODO: implement build
return Scaffold(
body: Container(
height: height * 1,
width: width * 1,
color: Colors.red,
child: Column(
children: [
Stack(
children: [
ClipPath(
clipper: CurvedAppBar(),
child: Container(
height: height * 0.2,
width: double.infinity,
color: Colors.white,
),
),
Positioned(child: Image.asset('assets/images/logo-with-bg.png'))
],
)
],
),
),
);
}
}
import 'package:flutter/material.dart';
class CurvedAppBar extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, size.height);
var firstStart = Offset(size.width / 5, size.height);
var firstEnd = Offset(size.width / 2.25, size.height - 50);
path.quadraticBezierTo(
firstStart.dx, firstEnd.dy, firstEnd.dx, firstEnd.dy);
var secondStart =
Offset(size.width - (size.width / 3.24), size.height - 105);
var secondEnd = Offset(size.width, size.height - 10);
path.quadraticBezierTo(
secondStart.dx, secondStart.dy, secondEnd.dx, secondEnd.dy);
path.lineTo(size.width, 0);
path.close();
return path;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
// TODO: implement shouldReclip
return false;
}
}
Any ideas how this can be shaped?
Check this out:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Center(
child: Container(
color: Colors.grey,
child: ClipPath(
clipper: Clipp(),
child: Container(
width: 500,
height: 500,
color: Colors.pink,
),
),
),
),
),
);
}
}
class Clipp extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.moveTo(150, 0);
path.quadraticBezierTo(120, 150, 0, 150);
path.lineTo(0, 380);
path.quadraticBezierTo(size.width / 4, size.height, size.width, 270);
path.lineTo(size.width, 0);
return path;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
The output:
Edit: To make it dynamic, try this:
class Clipp extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = Path();
double firstFactor = size.width / 3.3333;
double secondFactor = size.height / 2;
double thirdFactor = size.width / 4.166;
double fourthFactor = size.height / 1.4285;
path.moveTo(firstFactor, 0);
path.quadraticBezierTo(thirdFactor, firstFactor, 0, firstFactor);
path.lineTo(0, fourthFactor);
path.quadraticBezierTo(
size.width / 3,
size.height,
size.width,
secondFactor,
);
path.lineTo(size.width, 0);
return path;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}

How to code rectangle+ellipse shape in Flutter

I'm trying to achieve shape in the shown image. I can't find out how to do this. Last thing I tried was:
Container(
height: 175,
decoration: BoxDecoration(
borderRadius: BorderRadius.vertical(
bottom: Radius.elliptical(175, 45),
),
),
)
How can I create this shape?
You can use custom painter:
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Container(
color: Colors.transparent,
height: 155,
width: 375,
child: CustomPaint(
painter: CurvePainter(),
),
),
);
}
}
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Color(0XFF382b47);
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, size.height * 0.26);
path.quadraticBezierTo(
size.width / 2, size.height, size.width, size.height * 0.26);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
View Image
If you want to add ovel shape on top borders:
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(math.pi),
child: Container(
color: Colors.red,
height: 120,
width: double.infinity,
child: CustomPaint(
painter: CurvePainter(),
),
),
),;
}
}
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Color(0XFF382b47);
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, size.height * 0.26);
path.quadraticBezierTo(
size.width / 2, size.height, size.width, size.height * 0.26);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

I want make this curve in the container

This image show what I want to do ,, I used container and made border radius to bottom right and this is ok , but in bottom left I don’t know how to make this curve
You can easily do it using CustomPainter.
Please check the following example.
import 'package:flutter/material.dart';
void main() async {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Container(
color: Colors.white,
child: CustomPaint(
painter: CurvePainterPage(),
),
),
),
);
}
}
class CurvePainterPage extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.blue[800];
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, size.height * .70);
path.quadraticBezierTo(
0, size.height * .60, size.width * .1565, size.height * .60);
path.lineTo(size.width * .60, size.height * .60);
path.quadraticBezierTo(size.width * .69, size.height * .60,
size.width * .70, size.height * .50);
path.lineTo(size.width * .70, 0);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
You can read about it more here
You can use BoxDecoration inside the Container.
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,),
child:Text(
'Greetings, planet!',
style: TextStyle(
fontSize: 20,
color: Colors.grey[300],
),))

flutter design Curves layout as single widget

Here solved question about design this layout.
I have a problem to using that, because of this curve on right of screen is not widget and when I want to have some other widgets in green side, I can't, because designed curve is not widget its clipped from green layout.
Suppose I want to have this curve on right of screen and some widget in below of that.
Source code
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: Test())));
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
double _height = 0.0;
double _width = 0.0;
double _rightPadding = 2.0;
double _btnSize = 25.0;
double _btnY = 0.0;
#override
Widget build(BuildContext context) {
if (_height == 0.0)
setState(() {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
_btnY = _height / 3 * 2;
});
return _height == 0.0
? Container()
: Stack(
children: <Widget>[
Container(
color: Colors.white,
),
CustomPaint(
size: Size(_width - _rightPadding, _height),
painter: CurvedPainter(_btnSize, _btnY),
),
],
);
}
}
class CurvedPainter extends CustomPainter {
CurvedPainter(this.btnSize, this.btnY);
final double btnSize;
final double btnY;
#override
void paint(Canvas canvas, Size size) {
Path path = Path();
path.moveTo(0.0, 0.0);
path.lineTo(size.width, 0.0);
path.lineTo(size.width, btnY - btnSize * 2);
path.cubicTo(size.width, btnY - btnSize * 0.3, size.width - btnSize * 0.95, btnY - btnSize * 0.9, size.width - btnSize, btnY);
path.cubicTo(size.width - btnSize * 0.95, btnY + btnSize * 0.9, size.width, btnY + btnSize * 0.3, size.width, btnY + btnSize * 2);
path.lineTo(size.width, size.height);
path.lineTo(0.0, size.height);
path.lineTo(0.0, 0.0);
canvas.drawPath(
path,
Paint()
..color = Colors.transparent
..style = PaintingStyle.fill);
}
#override
bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}
I want to use right curve as an widget on top of all widgets, without having green side, you suppose green side is as ListView.
It seems that you need something like this given in the image below.
Update: Dragging control added
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Test(),
),
);
}
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
enum dragType { vertical, horizontal }
class _TestState extends State<Test> {
final double _btnSize = 48.0;
final double _rightPadding = 0;
double _extraOffcet = 0;
double _btnY;
double _currentX;
double _currentY;
double _height;
double _width;
bool _isHorizontalActive = true;
bool _isVerticalActive = true;
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
super.initState();
}
_afterLayout(_) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
_btnY = _height / 2;
setState(() {});
}
_onDrag(details) {
_updateCoordinates(
details.globalPosition.dx,
details.globalPosition.dy,
);
}
_updateCoordinates(double x, double y) {
setState(() {
if (_isHorizontalActive) {
_updateX(x);
}
if (_isVerticalActive) {
_updateY(y);
}
});
}
_updateX(x) {
var dx = _currentX - x;
_currentX = x;
_extraOffcet = _extraOffcet + dx;
_extraOffcet = math.max(_extraOffcet, _rightPadding);
_extraOffcet = math.min(_extraOffcet, _width - _btnSize);
}
_updateY(y) {
var dy = _currentY - y;
_currentY = y;
_btnY = _btnY - dy;
_btnY = math.max(_btnY, _btnSize);
_btnY = math.min(_btnY, _height - _btnSize);
}
_listItem(String text, double height) {
return Container(
height: height,
child: Text(text, style: TextStyle(fontSize: 20.0)),
);
}
#override
Widget build(BuildContext context) {
return _height == null
? Container()
: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(right: 30),
color: Colors.blue,
height: double.infinity,
width: double.infinity,
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
_buildSwitch(type: dragType.vertical),
_buildSwitch(type: dragType.horizontal),
...List.generate(
4,
(index) => _listItem('inside', 80),
),
]),
),
Positioned(
right: _extraOffcet + _rightPadding,
child: CustomPaint(
size: Size(_btnSize, _height),
painter: CurvedPainter(_btnSize, _btnY),
),
),
Positioned(
top: _btnY - _btnSize / 2 + 5,
right: _extraOffcet + _rightPadding + 5,
child: GestureDetector(
onPanDown: (details) {
_currentX = details.globalPosition.dx;
_currentY = details.globalPosition.dy;
},
onPanStart: _onDrag,
onPanUpdate: _onDrag,
child: Material(
type: MaterialType.circle,
color: Colors.white,
elevation: 8.0,
child: Container(
width: _btnSize - 10,
height: _btnSize - 10,
child: Icon(Icons.add),
),
),
),
),
Positioned(
top: 0,
left: _width - _extraOffcet,
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(8, (index) => _listItem('from right', 20)),
),
height: _height,
width: _width,
),
),
],
);
}
SwitchListTile _buildSwitch({dragType type}) {
Function onChange;
String titleText, sutitleText;
bool value;
if (type == dragType.horizontal) {
value = _isHorizontalActive;
titleText = 'Horizontal dragging';
onChange = (newValue) => setState(() => _isHorizontalActive = newValue);
} else {
value = _isVerticalActive;
titleText = 'Vertical dragging';
onChange = (newValue) => setState(() => _isVerticalActive = newValue);
}
sutitleText = value ? 'active' : 'disabled';
return SwitchListTile(
value: value,
onChanged: onChange,
title: Text(titleText),
subtitle: Text(sutitleText),
);
}
}
class CurvedPainter extends CustomPainter {
CurvedPainter(this.btnSize, this.btnY);
final double btnSize;
final double btnY;
#override
void paint(Canvas canvas, Size size) {
var halfBtnSize = btnSize / 2;
var xMax = size.width;
var yMax = size.height;
var path = Path()
..moveTo(halfBtnSize, yMax)
..lineTo(halfBtnSize, btnY + halfBtnSize * 2)
..cubicTo(halfBtnSize, btnY + halfBtnSize, 0, btnY + halfBtnSize, 0, btnY)
..cubicTo(0, btnY - halfBtnSize, halfBtnSize, btnY - halfBtnSize, halfBtnSize,
btnY - halfBtnSize * 2)
..lineTo(halfBtnSize, 0)
..lineTo(xMax, 0)
..lineTo(xMax, yMax);
canvas.drawPath(
path,
Paint()
..color = Colors.white
..style = PaintingStyle.fill);
}
#override
bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}