這篇文章將為大家詳細(xì)講解有關(guān)怎么在Flutter中利用Clipper自定義形狀,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
成都創(chuàng)新互聯(lián)企業(yè)建站,十多年網(wǎng)站建設(shè)經(jīng)驗,專注于網(wǎng)站建設(shè)技術(shù),精于網(wǎng)頁設(shè)計,有多年建站和網(wǎng)站代運營經(jīng)驗,設(shè)計師為客戶打造網(wǎng)絡(luò)企業(yè)風(fēng)格,提供周到的建站售前咨詢和貼心的售后服務(wù)。對于成都網(wǎng)站制作、網(wǎng)站建設(shè)中不同領(lǐng)域進(jìn)行深入了解和探索,創(chuàng)新互聯(lián)在網(wǎng)站建設(shè)中充分了解客戶行業(yè)的需求,以靈動的思維在網(wǎng)頁中充分展現(xiàn),通過對客戶行業(yè)精準(zhǔn)市場調(diào)研,為客戶提供的解決方案。
ClipOval 圓形裁剪
ClipOval( child: SizedBox( width: 120.0, height: 120.0, child: Image.asset( Config.assets_avatar_1, ), ), );
CircleAvatar 圓形頭像
CircleAvatar( radius: 60.0, backgroundImage: AssetImage( Config.assets_avatar_1, ), );
Container Decoration 裝飾形狀
通過BoxShape.circle實現(xiàn)圓形圖片
Container( width: 120.0, height: 120.0, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: AssetImage( Config.assets_avatar_1, ), ), ) );
通過BorderRadius實現(xiàn)圓形圖片
Container( width: 120.0, height: 120.0, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(60.0)), image: DecorationImage( image: AssetImage( Config.assets_avatar_1, ), ), ), )
ClipPath 路徑剪裁
ClipPath( clipper: TriangleClipper(ClipperPosition.LeftTop), child: Container( width: 16.0, height: 16.0, decoration: BoxDecoration( color: Colors.blue, ), ), ); enum ClipperPosition { LeftTop, RightTop, } class TriangleClipper extends CustomClipper{ final ClipperPosition position; TriangleClipper(this.position); @override Path getClip(Size size) { final path = Path(); path.lineTo(0.0, 0.0); if (position == ClipperPosition.LeftTop) { path.lineTo(size.width, 0.0); path.lineTo(size.width, size.height); } else if (position == ClipperPosition.RightTop) { path.lineTo(size.width, 0.0); path.lineTo(0.0, size.height); } path.close(); return path; } @override bool shouldReclip(CustomClipper oldClipper) { return false; } }
ClipRect 矩形剪裁
Container( alignment: Alignment.topCenter, color: Colors.transparent, child: Container( color: Colors.green, child: ClipRect( clipper: _RectClipper(20.0), child: Image.asset( Config.assets_avatar_1, width: 160.0, height: 160.0, fit: BoxFit.fill, ), ), ), ); class _RectClipper extends CustomClipper{ /// Remove side of size final double removeSize; _RectClipper(this.removeSize); @override Rect getClip(Size size) { return new Rect.fromLTRB( removeSize, removeSize, size.width - removeSize, size.height - removeSize, ); } @override bool shouldReclip(CustomClipper oldClipper) { return false; } }
ClipRRect 圓角矩形剪裁
ClipRRect( borderRadius: BorderRadius.all(Radius.circular(16.0)), child: Image.asset( Config.assets_avatar_1, fit: BoxFit.fill, width: 120.0, height: 120.0, ), );
Star Rating(CustomPaint) 評分控件
評分控件 UI圖
實現(xiàn)方案
使用CustomPaint結(jié)合ClipPath畫出單個五角星;
使用Stack渲染兩層畫面
背景層,一排灰色五角星 前景層,一排亮色五角星,并使用ClipRect截取一定Width
實現(xiàn)代碼
class StarRatingDemo extends StatefulWidget { @override _StarRatingDemoState createState() => _StarRatingDemoState(); } class _StarRatingDemoState extends State{ /// ClipPath Star Rating _buildClipPathStarRating(double rate, int count) { return Container( padding: EdgeInsets.fromLTRB(24.0, 16.0, 24.0, 0.0), child: StaticRatingBar( size: 50.0, rate: rate, count: count, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text('Star Rating'), ), body: ListView( physics: BouncingScrollPhysics(), children: [ // _buildClipPathStarRating(1.0, 1), _buildClipPathStarRating(0.5, 5), _buildClipPathStarRating(2.0, 5), _buildClipPathStarRating(3.0, 5), _buildClipPathStarRating(4.0, 5), _buildClipPathStarRating(5.0, 5), _buildClipPathStarRating(5.5, 6), SizedBox(height: 16.0), ], ), ); } } class StaticRatingBar extends StatelessWidget { /// Number of stars final int count; /// Init rate final double rate; /// Size of the starts final double size; final Color colorLight; final Color colorDark; StaticRatingBar({ this.rate = 5, this.colorLight = const Color(0xFF1E88E5), this.colorDark = const Color(0xFFEEEEEE), this.count = 5, this.size = 60, }); Widget buildDarkStar() { return SizedBox( width: size * count, height: size, child: CustomPaint( painter: _PainterStars( count: count, color: colorDark, strokeWidth: 0.0, size: this.size / 2, style: PaintingStyle.fill, ), ), ); } Widget buildLightStar() { return ClipRect( clipper: _RatingBarClipper(rate * size), child: SizedBox( height: size, width: size * count, child: CustomPaint( painter: _PainterStars( count: count, strokeWidth: 0.0, color: colorLight, size: this.size / 2, style: PaintingStyle.fill, ), ), ), ); } @override Widget build(BuildContext context) { return Stack( children: [ buildDarkStar(), buildLightStar(), ], ); } } class _RatingBarClipper extends CustomClipper { final double width; _RatingBarClipper(this.width); @override Rect getClip(Size size) { return Rect.fromLTRB(0.0, 0.0, width, size.height); } @override bool shouldReclip(_RatingBarClipper oldClipper) { return false; } } class _PainterStars extends CustomPainter { final double size; final int count; final Color color; final PaintingStyle style; final double strokeWidth; _PainterStars({ this.size, this.count, this.color, this.strokeWidth, this.style, }); double degree2Radian(int degree) { return (pi * degree / 180); } Path createStarPath(double radius, Path path) { double radian = degree2Radian(36); double radiusIn = (radius * sin(radian / 2) / cos(radian)) * 1.1; path.moveTo((radius * cos(radian / 2)), 0.0); path.lineTo( (radius * cos(radian / 2) + radiusIn * sin(radian)), (radius - radius * sin(radian / 2)), ); path.lineTo( (radius * cos(radian / 2) * 2), (radius - radius * sin(radian / 2)), ); path.lineTo( (radius * cos(radian / 2) + radiusIn * cos(radian / 2)), (radius + radiusIn * sin(radian / 2)), ); path.lineTo( (radius * cos(radian / 2) + radius * sin(radian)), (radius + radius * cos(radian)), ); path.lineTo((radius * cos(radian / 2)), (radius + radiusIn)); path.lineTo( (radius * cos(radian / 2) - radius * sin(radian)), (radius + radius * cos(radian)), ); path.lineTo( (radius * cos(radian / 2) - radiusIn * cos(radian / 2)), (radius + radiusIn * sin(radian / 2)), ); path.lineTo(0.0, (radius - radius * sin(radian / 2))); path.lineTo( (radius * cos(radian / 2) - radiusIn * sin(radian)), (radius - radius * sin(radian / 2)), ); path.lineTo((radius * cos(radian / 2)), 0.0); return path; } @override void paint(Canvas canvas, Size size) { Paint paint = Paint(); paint.strokeWidth = strokeWidth; paint.color = color; paint.style = style; Path path = Path(); double offset = strokeWidth > 0 ? strokeWidth + 2 : 0.0; path = createStarPath(this.size - offset, path); for (int i = 0; i < count - 1; i++) { path = path.shift(Offset(this.size * 2, 0.0)); path = createStarPath(this.size - offset, path); } if (offset > 0) { path = path.shift(Offset(offset, offset)); } path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(_PainterStars oldDelegate) { return oldDelegate.size != this.size; } }
關(guān)于怎么在Flutter中利用Clipper自定義形狀就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。