写点什么

【Flutter 专题】116 图解 PhysicalModel & PhysicalShape 裁切小组件

发布于: 2021 年 06 月 01 日
【Flutter 专题】116 图解 PhysicalModel & PhysicalShape 裁切小组件

    小菜在学习过程中发现仅通过设置 decoration 是无法改变 Container 内部 Widget 样式的,一般我们会通过 ClipX 方式进行裁剪;而一旦涉及到 Widget 的裁剪,对于基础样式,通常会采用 ClipOval / ClipRRect / ClipPath 等方式,对于稍加复杂的样式,一般通过自定义 CustomClipper 也可以满足;


    而小菜今天尝试另一种类似的 PhysicalModel 方式;PhysicalX 方式可以设置 Widget 阴影效果,而 ClipX 方式不行;



PhysicalModel

源码分析

const PhysicalModel({    Key key,    this.shape = BoxShape.rectangle,    // 裁剪样式    this.clipBehavior = Clip.none,      // 裁剪方式    this.borderRadius,                  // 圆角弧度    this.elevation = 0.0,               // 阴影高度    @required this.color,               // 背景色    this.shadowColor = const Color(0xFF000000),     // 阴影颜色    Widget child,})
复制代码


    分析源码可得,PhysicalModel 是一个样式相对单一的裁切 Widget,其中 color 背景色是必不可少的,而真正影响阴影颜色的为 shadowColor

案例尝试

1. shape & borderRadius

    shape 为裁剪样式,包括 BoxShape.rectangleBoxShape.circle 两种,分别对应 ClipRRectClipOval,而 borderRadius 只有在 rectangle 圆角情况下生效;其中 clipBehavior 与其他涉及到裁切方式一致;


// ClipXreturn ClipRRect(    borderRadius: BorderRadius.all(Radius.circular(20.0)),    child: Container(width: 80.0, height: 80.0, child: Image.asset('images/icon_hzw01.jpg')));return Container(    width: 80.0, height: 80.0,    child: ClipOval(child: Image.asset('images/icon_hzw01.jpg', fit: BoxFit.fill)));
// PhysicalModelreturn PhysicalModel( color: Colors.transparent, shape: isCircle ? BoxShape.circle : BoxShape.rectangle, clipBehavior: Clip.antiAlias, borderRadius: BorderRadius.all(Radius.circular(20.0)), child: Container(width: 80.0, height: 80.0, child: Image.asset('images/icon_hzw01.jpg')));
复制代码



2. color & shadowColor

    color 对应 Widget 裁切的背景色,阴影效果是根据当前背景色展示,shadowColor 可以设置阴影颜色;


return PhysicalModel(    color: Colors.teal.withOpacity(0.6),    shape: isCircle ? BoxShape.circle : BoxShape.rectangle,    clipBehavior: Clip.antiAlias,    elevation: 6.0,    shadowColor: isCircle ? Colors.yellow : Colors.deepOrange,    borderRadius: BorderRadius.all(Radius.circular(20.0)),    child: Container(width: 80.0, height: 80.0, color: Colors.pink.withOpacity(0.2)));
复制代码



PhysicalShape

源码分析

const PhysicalShape({    Key key,    @required this.clipper,    this.clipBehavior = Clip.none,    this.elevation = 0.0,    @required this.color,    this.shadowColor = const Color(0xFF000000),    Widget child,})
复制代码


    分析源码可得,PhysicalShapeClipPath 类似,均是通过 clipper 方式自定义裁切方式;

案例尝试

    小菜尝试裁切一个多边形图片,通过自定义 CustomClipper 来设置裁切样式;


return ClipPath(    clipBehavior: Clip.antiAlias,    clipper: PolygonClipper(10),    child: Container(width: 80.0, height: 80.0, child: Image.asset('images/icon_hzw01.jpg')));
return PhysicalShape( color: Colors.transparent, clipBehavior: Clip.antiAlias, clipper: PolygonClipper(10), shadowColor: Colors.deepOrange, elevation: 6.0, child: Container(width: 80.0, height: 80.0, child: Image.asset('images/icon_hzw01.jpg')));
class PolygonClipper extends CustomClipper<Path> { final int num; PolygonClipper(this.num);
@override Path getClip(Size size) { double radius = size.width * 0.5; Path _path = Path(); var startX = size.width * 0.5 + radius * cos(2 * pi * 0 / num); var startY = size.height * 0.5 + radius * sin(2 * pi * 0 / num); _path.moveTo(startX, startY); for (var i = 1; i <= num; i++) { var newX = size.width * 0.5 + radius * cos(2 * pi * i / num); var newY = size.height * 0.5 + radius * sin(2 * pi * i / num); _path.lineTo(newX, newY); } _path.close(); return _path; }
@override bool shouldReclip(CustomClipper<Path> oldClipper) => true;}
复制代码





    PhysicalModel & PhysicalShape 案例源码




    小菜对于更深入的裁切方式还不够深入,Flutter 同时提供了对应带有动画效果的 AnimatedPhysicalModel;如有错误,请多多指导!


来源: 阿策小和尚

发布于: 2021 年 06 月 01 日阅读数: 7
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】116 图解 PhysicalModel & PhysicalShape 裁切小组件