Flutter 如何在使用自定义滚动视图时(或内部)显示自定义剪辑器

Posted

技术标签:

【中文标题】Flutter 如何在使用自定义滚动视图时(或内部)显示自定义剪辑器【英文标题】:Flutter how to display a Custom Clipper when (or inside) using a Custom Scroll View 【发布时间】:2021-03-02 21:19:48 【问题描述】:

所以这就是交易。我在一个名为 WaveClipper 的类中创建了(有点)一个形状像波浪的自定义剪辑器

削波器类:

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;
  

每当我使用脚手架显示它时,它都显示得很好,但是当我尝试将它推到位于 CustomScrollView 内的 SliverListView 中时,什么也没有出现,也没有错误。剪辑器是否在内容下方?以及如何显示它。

我要展示的剪纸器:

         Stack(
            children: [
              ClipPath(
                  clipper: WaveClipper(),
                  child: Container(
                    color: Colors.cyanAccent,
                  ))
               ],
             ),

我想在哪里展示它:

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)
        ]),
      ),
    ],
  ),
)

感谢您的帮助,感谢您抽出宝贵的时间。

【问题讨论】:

【参考方案1】:

试着给你的Container一些维度:

Stack(
  children: [
    ClipPath(
      clipper: WaveClipper(),
      child: Container(
        height: 300,
        color: Colors.amber.shade200,
      ),
    ),
  ],
),

完整源代码

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;
  

【讨论】:

嗨蒂埃里!没用,但尺寸绝对是一个因素,我找到了一种解决方法,虽然它不是一个很好的方法,我正在更新问题,让我知道任何建议。 奇怪,用完整的源代码示例检查我的更新答案。【参考方案2】:
        Container(
            height: device.size.height * 0.3,
            child: Scaffold(
              body: Stack(
                clipBehavior: Clip.none,
                children: [
                  ClipPath(
                      clipper: WaveClipper(),
                      child: Container(
                        color: Colors.cyanAccent,
                      ))
                ],
              ),
            ),
          ),

用 Scaffold 包裹并使用 Container 为 Scaffold 指定大小,如果有人有更好的解决方案,请务必发布。

【讨论】:

【参考方案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;
  

【讨论】:

请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。

以上是关于Flutter 如何在使用自定义滚动视图时(或内部)显示自定义剪辑器的主要内容,如果未能解决你的问题,请参考以下文章

如何在带有 Flutter 的可滚动视图中拥有具有可变高度内容的 TabView?

滚动时隐藏自定义表格视图单元格标签如何解决?

自定义视图在缩放后重绘时如何防止“反弹”效果?

具有自定义视图的 NSMenuItem 在滚动时消失

打开聊天Flutter时如何向下滚动聊天列表视图

如何在我自己的自定义视图中重现 iPhone UIScrollView 的轻弹滚动行为?