Flutter 裁剪布局之 ClipRect、ClipRRect、ClipOval、ClipPath、CustomClipper


https://blog.csdn.net/ITxiaodong/article/details/105029358

文章目錄


參考:

 

裁剪布局

Flutter中提供了一些剪裁widget,如下表格。
widget 作用
ClipRect 將 child 剪裁為給定的矩形大小
ClipRRect 將 child 剪裁為圓角矩形
ClipOval 如果 child 為正方形時剪裁之后是圓形,如果 child 為矩形時,剪裁之后為橢圓形
ClipPath 將 child 按照給定的路徑進行裁剪
CustomClipper 並不是一個widget,但是使用CustomClipper可以繪制出任何我們想要的形狀
ClipRect

將 child 剪裁為給定的矩形大小
查看構造函數支持哪些字段:

 

const ClipRect({ 

Key key, 

this.clipper, // CustomClipper 對象,如果為空,則裁剪區域為 child 指定的大小

this.clipBehavior = Clip.hardEdge, // 裁剪的方式, 不能為 null 或者 Clip.none

Widget child // 子布局

 }

)

clipBehavior可選值有:none, hardEdge, antiAlias, antiAliasWithSaveLayer

none:不裁剪
hardEdge:裁剪但不應用抗鋸齒,裁剪速度比none模式慢一點,但比其他方式快。
antiAlias:裁剪而且抗鋸齒,以實現更平滑的外觀。裁剪速度比antiAliasWithSaveLayer快,比hardEdge慢。
antiAliasWithSaveLayer:帶有抗鋸齒的剪輯,並在剪輯之后立即保存saveLayer。
在這里插入圖片描述

 

代碼實現:

 

Column(

  children: <Widget>[

    Container(

      child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm'

      ),

    ),

    SizedBox(

      height: 30,

    ),

    ClipRect(

      child: Container(

        height: 150,

        width: 150,

        child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm',

          fit: BoxFit.cover,

        ),

      ),

    )

  ],

)

 

 

偽代碼:

 

Column(

  children: <Widget>[

    Container(

      child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm'

      ),

    ),

    SizedBox(

      height: 30,

    ),

    ClipRRect(

      borderRadius: BorderRadius.circular(20),// 圓角半徑

      child: Container(

        height: 150,

        width: 150,

        child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm',

          fit: BoxFit.cover,

        ),

      ),

    ),

  ],

)

 

ClipOval

 在這里插入圖片描述

如果 child 為正方形時剪裁之后是圓形,如果 child 為矩形時,剪裁之后為橢圓形。

構造函數中的字段同ClipRect。

 

偽代碼:

 

Column(

  children: <Widget>[

    Container(

      child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm'

      ),

    ),

    SizedBox(

      height: 30,

    ),

    ClipOval(// 寬高不一致為,裁剪后為橢圓形

      child: Container(

        height: 100,

        width: 150,

        child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm',

          fit: BoxFit.cover,

        ),

      ),

    ),

    SizedBox(

      height: 30,

    ),

    ClipOval(// 寬高一致為,裁剪后為圓形

      child: Container(

        height: 100,

        width: 100,

        child: Image.network(

          'https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm',

          fit: BoxFit.cover,

        ),

      ),

    ),

  ],

)

ClipPath 及 CustomClipper

 在這里插入圖片描述

ClipPath會將 child 按照給定的路徑進行裁剪,CustomClipper可以繪制出任何我們想要的形狀

實現的效果:實戰項目源碼可在 Flutter-WanAndroid 中查看。

 

 

上方的這種效果可以通過ClipPath+CustomClipper實現。

 

主要思路是通過CustomClipper實現自定義的斜線效果然后將結果傳遞給ClipPath構造函數中的clipper字段。

 

我們先來看看CustomClipper這個抽象類。

 在這里插入圖片描述

在源碼中可以看到getClip方法就是獲取裁剪的區域。我們可以在這個方法中繪制出斜對角效果。

 

偽代碼實現如下:

 

class _CustomClipperTestPageState extends State<CustomClipperTestPage> {

  @override

  Widget build(BuildContext context) {

    return Scaffold(

        appBar: AppBar(

          title: Text('ClipPath、CustomClipper'),

        ),

        body: Column(children: <Widget>[

          Stack(

            children: <Widget>[

              ClipPath(

                clipper:

                    TopBarClipper(MediaQuery.of(context).size.width, 200.0),

                child: Container(// 主題色填充 child

                  width: double.infinity,

                  height: 240.0,

                  color: Theme.of(context).primaryColor,

                ),

              ),

              // 名字

              Padding(

                padding: EdgeInsets.only(top: 40.0),

                child: Center(

                    child: Text(

                  '龍衣',

                  style: TextStyle(fontSize: 30.0, color: Colors.white),

                )),

              ),

              // 圓形頭像

              Container(

                margin: EdgeInsets.only(top: 100.0),

                child: Center(

                    child: Container(

                        width: 100.0,

                        height: 100.0,

                        child: ClipOval(

                            child: Image.network(

                          "https://ssyerv1.oss-cn-hangzhou.aliyuncs.com/picture/389e31d03d36465d8acd9939784df6f0.jpg!sswm",

                          fit: BoxFit.fill,

                        )))),

              ),

            ],

          ),

        ]));

  }

}

 

/// 頂部斜對角欄裁剪

class TopBarClipper extends CustomClipper<Path> {

  // 寬高

  double width;

  double height;

 

  /// 構造函數,接收傳遞過來的寬高

  TopBarClipper(this.width, this.height);

 

  /// 獲取剪裁區域的接口

  /// 返回斜對角的圖形 path

  @override

  Path getClip(Size size) {

    Path path = Path();

    path.moveTo(0.0, 0.0);

    path.lineTo(width, 0.0);

    // path 斜線效果

    path.lineTo(width, height / 2);

    path.lineTo(0.0, height);

    path.close();

    return path;

  }

 

  /// 接口決定是否重新剪裁

  /// 如果在應用中,剪裁區域始終不會發生變化時應該返回 false,這樣就不會觸發重新剪裁,避免不必要的性能開銷。

  @override

  bool shouldReclip(CustomClipper<Path> oldClipper) {

    return false;

  }

}

 

完~

————————————————

版權聲明:本文為CSDN博主「_龍衣」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/ITxiaodong/article/details/105029358

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM