'Flutter how to display a Custom Clipper when (or inside) using a Custom Scroll View
so here's the deal. I created (sort of) a custom clipper shaped like a wave inside a class called WaveClipper
the wave clipper class:
class WaveClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, 220);
path.quadraticBezierTo(size.width / 4, 160 , size.width / 2, 175);
path.quadraticBezierTo(3 / 4 * size.width, 190, size.width, 130);
path.lineTo(size.width, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
And whenever I display it using a scaffold it shows fine however when I try to push it inside a SliverListView which is inside a CustomScrollView then nothing appears and there are no errors either. Is the clipper under the content? And how can I display it.
the clipper I am trying to show:
Stack(
children: [
ClipPath(
clipper: WaveClipper(),
child: Container(
color: Colors.cyanAccent,
))
],
),
where I am trying to show it:
Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
iconTheme: IconThemeData(
color: Colors.cyanAccent,
),
),
backgroundColor: Colors.white,
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverList(
delegate: SliverChildListDelegate([
//here
//there rest of the content (mostly buttons)
]),
),
],
),
)
Any help is appreciated and thank you for taking the time.
Solution 1:[1]
Try to give some dimension to your Container
:
Stack(
children: [
ClipPath(
clipper: WaveClipper(),
child: Container(
height: 300,
color: Colors.amber.shade200,
),
),
],
),
Full source code
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
iconTheme: IconThemeData(
color: Colors.cyanAccent,
),
),
backgroundColor: Colors.white,
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverList(
delegate: SliverChildListDelegate([
Stack(
children: [
ClipPath(
clipper: WaveClipper(),
child: Container(
height: 300,
color: Colors.amber.shade200,
),
),
],
),
]),
),
],
),
);
}
}
class WaveClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, 220);
path.quadraticBezierTo(size.width / 4, 160, size.width / 2, 175);
path.quadraticBezierTo(3 / 4 * size.width, 190, size.width, 130);
path.lineTo(size.width, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
Solution 2:[2]
Container(
height: device.size.height * 0.3,
child: Scaffold(
body: Stack(
clipBehavior: Clip.none,
children: [
ClipPath(
clipper: WaveClipper(),
child: Container(
color: Colors.cyanAccent,
))
],
),
),
),
Wrap with a Scaffold and give that Scaffold a size using a Container, if anyone has a better solution by all means post it.
Solution 3:[3]
import 'package:flutter/material.dart';
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Stack(
children: [
Opacity(opacity: 0.5,
child: ClipPath(
clipper: WaveClipper(),
child: Container(color: Colors.red,
height: 200,),
),
),
ClipPath(
clipper: WaveClipper(),
child: Container(color: Colors.deepOrange,
height: 180,),
),
],
),
),
);
}
}
class WaveClipper extends CustomClipper<Path>{
@override
Path getClip(Size size){
debugPrint(size.width.toString());
var path = new 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, firstStart.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(CustomClipper<Path> oldClipper) {
return false;
}
}
Solution 4:[4]
Optionally add dotted_decoration package if needed: https://pub.dev/packages/dotted_decoration
import 'package:flutter/material.dart';
import 'package:dotted_decoration/dotted_decoration.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: DiscountTile()),
);
}
}
class DiscountTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: _DiscountTileClipper(),
child: Container(
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(16)),
),
child: ColoredBox(
color: Colors.blue,
child: Row(
children: [
SizedBox(width: 100),
Expanded(
child: DecoratedBox(
decoration: DottedDecoration(
linePosition: LinePosition.left,
color: Colors.red,
strokeWidth: 3,
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('hello world' * 20),
),
),
),
],
),
),
),
);
}
}
class _DiscountTileClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
const Radius radius = Radius.circular(1);
const bool clockwise = false;
const double clipRadius = 20;
const double decreaseValueWidgetWidth = 100.0;
const double leftPadding = decreaseValueWidgetWidth + 9;
return Path()
..lineTo(leftPadding - clipRadius, 0)
..arcToPoint(
const Offset(leftPadding, 0),
clockwise: clockwise,
radius: radius,
)
..lineTo(size.width, 0)
..lineTo(size.width, size.height)
..lineTo(leftPadding, size.height)
..arcToPoint(
Offset(leftPadding - clipRadius, size.height),
clockwise: clockwise,
radius: radius,
)
..lineTo(0, size.height)
..close();
}
@override
bool shouldReclip(_DiscountTileClipper oldClipper) => true;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Andrea herrera |
Solution 3 | Rohit Kushwaha |
Solution 4 | Yauheni Prakapenka |