想要仅在CustomClipper <Path>边框上添加高程,而不是下面的整个材质

时间:2019-12-08 14:09:09

标签: android flutter

我正在尝试通过使用Material的高程在自定义路径上添加高程,但是好像没有做 任何事情,我都尝试过其他方法,但是整个材料(矩形)都得到了提升。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.pink[300],
        body: Column(
          children: <Widget>[
            TopContainer(),
          ],
        ));
  }
}

class TopContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ClipPath(
        clipper: ImageClipper(),
        child: Material(
          elevation: 15.0,
          child: Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                fit: BoxFit.cover,
                image: NetworkImage(
                  'https://images.pexels.com/photos/3309467/pexels-photo-3309467.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
                ),
              ),
            ),
            constraints: BoxConstraints.expand(
              width: double.infinity,
              height: MediaQuery.of(context).size.height * 0.5,
            ),
          ),
        ));
  }
}

class ImageClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();
    path.lineTo(0.0, size.height);
    var firstControlPoint = Offset(size.width * 0.35, size.height * 0.75);
    var firstEndPoint = Offset(size.width * 0.65, size.height * 0.85);
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstEndPoint.dx, firstEndPoint.dy);
    ///////////////////////////////////////////////
    var secondControlPoint = Offset(size.width * 0.85, size.height * 0.90);
    var secondEndPoint = Offset(size.width, size.height * 0.75);
    path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
        secondEndPoint.dx, secondEndPoint.dy);

    //    path.lineTo(size.width, size.height * 0.9);
    path.lineTo(size.width, 0.0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return false;
  }
}

我正在尝试通过使用Material的高程在自定义路径上添加高程,但是似乎什么也没做,我尝试了其他方法,但在整个材料(矩形)上获得了高程。

enter image description here

1 个答案:

答案 0 :(得分:1)

使用该自定义ShapeBorder

class WaveShapeBorder extends ShapeBorder {
  @override EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
  @override ui.Path getInnerPath(ui.Rect rect, {ui.TextDirection textDirection}) => null;

  @override
  ui.Path getOuterPath(ui.Rect rect, {ui.TextDirection textDirection}) {
    var ctrl1 = FractionalOffset(0.35, 0.75).withinRect(rect);
    var end1  = FractionalOffset(0.65, 0.85).withinRect(rect);
    var ctrl2 = FractionalOffset(0.85, 0.90).withinRect(rect);
    var end2  = FractionalOffset(1.0,  0.75).withinRect(rect);
    return Path()
      ..moveTo(rect.topLeft.dx, rect.topLeft.dy)
      ..lineTo(rect.bottomLeft.dx, rect.bottomLeft.dy)
      ..quadraticBezierTo(ctrl1.dx, ctrl1.dy, end1.dx, end1.dy)
      ..quadraticBezierTo(ctrl2.dx, ctrl2.dy, end2.dx, end2.dy)
      ..lineTo(rect.topRight.dx, rect.topRight.dy)
      ..close();
  }

  @override void paint(ui.Canvas canvas, ui.Rect rect, {ui.TextDirection textDirection}) {}
  @override ShapeBorder scale(double t) => this;
}

和此示例代码进行测试:

class WaveShapeBorderTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.teal, Colors.green],
          begin: Alignment.topRight,
          end: Alignment.centerLeft,
        ),
      ),
      child: Stack(
        children: [
          Material(
            elevation: 6,
            shape: WaveShapeBorder(),
            clipBehavior: Clip.antiAlias,
            child: Image.asset('images/someImage.png'),
          ),
        ],
      ),
    );
  }
}

当然,您可以自由使用它,但是主要思想是使用Material.shapeMaterial.clipBehavior属性

这是最终结果:

enter image description here

编辑,如果您认为阴影太“浅”,则可以使用自定义阴影添加另外一个Container

class WaveShapeBorderTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.teal, Colors.green],
          begin: Alignment.topRight,
          end: Alignment.centerLeft,
        ),
      ),
      child: Stack(
        children: [
          Container(
            decoration: ShapeDecoration(
              shape: WaveShapeBorder(),
              shadows: [
                BoxShadow(color: Colors.black, blurRadius: 16, offset: Offset(2, 2), spreadRadius: 8),
              ]
            ),
            child: Material(
              clipBehavior: Clip.antiAlias,
              shape: WaveShapeBorder(),
              child: Image.asset('images/someImage.png',),
            ),
          ),
          Icon(Icons.photo, size: 64,),
        ],
      ),
    );
  }
}

您将看到:

enter image description here