Flutter 颤振:使剪切区域对滚动列表视图透明
我有一个Flutter 颤振:使剪切区域对滚动列表视图透明,flutter,listview,clipping,Flutter,Listview,Clipping,我有一个列表视图,当它点击另一个小部件的剪辑时,我想“消失” 这是我的密码 import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage
列表视图
,当它点击另一个小部件的剪辑时,我想“消失”
这是我的密码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TopWidget(),
Expanded(
child: ListView(
itemExtent: 100,
children: <Widget>[
Card(color: Colors.green,),
],
),
),
],
),
);
}
}
class TopWidget extends StatelessWidget {
TopWidget();
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: ShadowPainter(),
child: ClipPath(
clipper: TopWidgetClipper(),
child: Container(
height: 370,
color: Colors.blue,
),
),
);
}
}
class TopWidgetClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Offset controllPoint1 = Offset(0, size.height - 100);
Offset endPoint1 = Offset(100, size.height - 100);
Offset controllPoint2 = Offset(size.width, size.height - 100);
Offset endPoint2 = Offset(size.width, size.height - 200);
Path path = Path()
..lineTo(0, size.height)
..quadraticBezierTo(
controllPoint1.dx, controllPoint1.dy, endPoint1.dx, endPoint1.dy)
..lineTo(size.width - 100, size.height - 100)
..quadraticBezierTo(
controllPoint2.dx, controllPoint2.dy, endPoint2.dx, endPoint2.dy)
..lineTo(size.width, 0);
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
class ShadowPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Offset controllPoint1 = Offset(0, size.height - 100);
Offset endPoint1 = Offset(100, size.height - 100);
Offset controllPoint2 = Offset(size.width, size.height - 100);
Offset endPoint2 = Offset(size.width, size.height - 200);
Path path = Path()
..lineTo(0, size.height)
..quadraticBezierTo(
controllPoint1.dx, controllPoint1.dy, endPoint1.dx, endPoint1.dy)
..lineTo(size.width - 100, size.height - 100)
..quadraticBezierTo(
controllPoint2.dx, controllPoint2.dy, endPoint2.dx, endPoint2.dy)
..lineTo(size.width, 0);
canvas.drawShadow(path, Colors.grey[50], 3.0, false);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主页:MyHomePage(),
);
}
}
类MyHomePage扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:专栏(
儿童:[
TopWidget(),
扩大(
子:ListView(
项目范围:100,
儿童:[
卡片(颜色:Colors.green,),
],
),
),
],
),
);
}
}
类TopWidget扩展了无状态Widget{
TopWidget();
@凌驾
小部件构建(构建上下文){
返回自定义油漆(
画家:阴影画家(),
孩子:克利帕斯(
clipper:TopWidgetClipper(),
子:容器(
身高:370,
颜色:颜色,蓝色,
),
),
);
}
}
类TopWidgetClipper扩展了CustomClipper{
@凌驾
路径getClip(大小){
偏移量控制点1=偏移量(0,size.height-100);
偏移端点1=偏移(100,size.height-100);
偏移量控制点2=偏移量(大小.宽度,大小.高度-100);
偏移端点2=偏移(大小.宽度,大小.高度-200);
路径路径=路径()
..lineTo(0,尺寸。高度)
…方贝塞尔托(
ControlPoint1.dx,ControlPoint1.dy,endPoint1.dx,endPoint1.dy)
…lineTo(尺寸.宽度-100,尺寸.高度-100)
…方贝塞尔托(
ControlPoint2.dx,ControlPoint2.dy,endPoint2.dx,endPoint2.dy)
..lineTo(尺寸.宽度,0);
返回路径;
}
@凌驾
bool shouldReclip(CustomClipper oldClipper){
返回true;
}
}
类ShadowPainter扩展了CustomPainter{
@凌驾
空心油漆(帆布,尺寸){
偏移量控制点1=偏移量(0,size.height-100);
偏移端点1=偏移(100,size.height-100);
偏移量控制点2=偏移量(大小.宽度,大小.高度-100);
偏移端点2=偏移(大小.宽度,大小.高度-200);
路径路径=路径()
..lineTo(0,尺寸。高度)
…方贝塞尔托(
ControlPoint1.dx,ControlPoint1.dy,endPoint1.dx,endPoint1.dy)
…lineTo(尺寸.宽度-100,尺寸.高度-100)
…方贝塞尔托(
ControlPoint2.dx,ControlPoint2.dy,endPoint2.dx,endPoint2.dy)
..lineTo(尺寸.宽度,0);
画布.drawShadow(路径,颜色.灰色[50],3.0,假);
}
@凌驾
bool应重新绘制(自定义代理){
返回true;
}
}
到目前为止,当我向下滚动时,当列表(绿色框)到达我裁剪的TopWidget
的容器底部(黄色边框)时,它就看不见了。但我希望列表只有在到达剪辑边缘时才能平滑地消失(如第二个屏幕截图中的蓝色区域)
你知道我怎样才能做到这一点吗?谢谢大家! 正如我从@pskink(谢谢)学到的,在这样的用例中,您需要小部件实际调整其边界(spoiler:shape),您应该使用不同小部件的
shape
属性,并在扩展shapeorder
的自定义类中使用本例中使用的路径。最简单的方法是:
容器(
身高:370,
装饰:造型装饰(
颜色:颜色,蓝色,
形状:AppBarBorder(),
///您还可以指定一些整洁的阴影投射到在这个阴影下滚动的小部件上
阴影:[
箱形阴影(
颜色:颜色。黑色。不透明度(0.7),
半径:18.0,
扩展半径:2.0,
),
],
),
),
和自定义类:
类AppBarBorder扩展了ShapeBorder{
@凌驾
路径getOuterPath(Rect Rect,{TextDirection TextDirection}){
偏移量控制点1=偏移量(0,rect.size.height-100);
偏移端点1=偏移(100,rect.size.height-100);
偏移量控制点2=偏移量(rect.size.width,rect.size.height-100);
偏移端点2=偏移(rect.size.width,rect.size.height-200);
返回路径()
…lineTo(0,矩形尺寸高度)
…方贝塞尔托(
ControlPoint1.dx,ControlPoint1.dy,endPoint1.dx,endPoint1.dy)
..lineTo(rect.size.width-100,rect.size.height-100)
…方贝塞尔托(
ControlPoint2.dx,ControlPoint2.dy,endPoint2.dx,endPoint2.dy)
..lineTo(rect.size.width,0);
}
@凌驾
EdgeInSetGeometry get dimensions=>EdgeInsets.only(底部:0);
@凌驾
路径getInnerPath(Rect Rect,{TextDirection TextDirection})=>null;
@凌驾
void paint(画布画布,Rect Rect,{TextDirection TextDirection}){
@凌驾
形状顺序比例(双t)=>此;
}
与声明CustomClipper
或CustomPainter
的方法几乎相同,因为您不需要实现这些方法中的大多数,基本上只需要关心getOuterPath
最后,我们需要重新构造布局本身,因为当前您有一个带有此自定义容器
形状的列
,下面是列表视图
。由于容器
不属于列表视图
的一部分,因此不能将其滚动到下面或其他位置。最简单的方法是使用堆栈
:
堆栈(
儿童:[
扩大(
子:ListView(
填充:仅限边缘设置(顶部:370.0),
项目范围:100,
儿童:[
卡片(
颜色:颜色。绿色,
),
],
),
),
容器(
身高:370,
装饰:造型装饰(
颜色:颜色,蓝色,
形状:AppBarBorder