Je suis nouveau dans le flutter et je suis tombé sur ce problème d'ajout d'images à des formes en scintillement. J'ai créé la forme personnalisée mais je ne peux pas y insérer d'image. Voici ce que je souhaite réaliser: Une image dans une forme personnalisée
J'ai essayé de donner Image en tant qu'enfant de CustomPainter mais toujours pas de bons résultats.
Quelqu'un peut-il suggérer une bonne approche?
3 Réponses :
Comme Midhun MP l'a mentionné, enveloppez votre image avec ClipPath
class AnyClipper extends CustomClipper<Path> { @override Path getClip(Size size) { var path = Path(); //... do something return path; } @override bool shouldReclip(CustomClipper<Path> oldClipper) => false; }
et utilisez CustomClipper
@override Widget build(BuildContext context) { return ClipPath( child: image, clipper: AnyClipper(), ); }
Merci @Me_ de m'avoir guidé :)
Comme Mindhun MP l'a écrit, vous devez utiliser un clipper personnalisé. Voici un exemple de découpage du conteneur:
class _CustomClipper extends CustomClipper<Path> { @override Path getClip(Size size) { final double heightDelta = size.height / 2.2; return Path() ..addRect( Rect.fromLTWH(0, heightDelta, size.width, size.height - heightDelta)) ..moveTo(0, heightDelta) ..quadraticBezierTo( size.width / 2, heightDelta - size.width / 2, size.width, heightDelta, ); } @override bool shouldReclip(CustomClipper<Path> oldClipper) => true; }
Votre cas devrait être similaire au mien, alors consultez la fonction quadraticBezierTo . Mon exemple:
ClipPath( clipper: _CustomClipper(), child: Container(...), );
Aussi here est un excellent article qui explique plus en détail les chemins dans Flutter.
Merci beaucoup @oziem. C'était un excellent exemple pour créer la forme souhaitée.
Avec CustomPaint, vous pouvez utiliser une image comme masque qui recouvre l'image d'origine et n'afficher que le contenu de l'image qu'elle contenait dans le masque. Ce qui dans ce cas est une forme. Dans le code ci-dessous, shape.png agit comme le masque, et seule la partie non transparente du fichier png affichera le contenu de image.jpeg . Vous devez donc créer un fichier png avec la forme souhaitée et l'appliquer en superposition à l'image.
import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; class MaskedImageWithPainter extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { ui.Image mask; ui.Image image; @override void initState() { super.initState(); load('assets/shape.png').then((i) { setState(() { mask = i; }); }); load('assets/image.jpeg').then((i) { setState(() { image = i; }); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(backgroundColor: Colors.blue, title: Text('I am a title')), body: SafeArea( child: SizedBox( width: 200.0, height: 200.0, child: CustomPaint(painter: OverlayPainter(mask, image)), ), ), ); } Future<ui.Image> load(String asset) async { ByteData data = await rootBundle.load(asset); ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List()); ui.FrameInfo fi = await codec.getNextFrame(); return fi.image; } } class OverlayPainter extends CustomPainter { ui.Image mask; ui.Image image; OverlayPainter(this.mask, this.image); @override void paint(Canvas canvas, Size size) { if (image != null && mask != null) { var rect = Rect.fromLTRB(0, 0, 200, 200); Size outputSize = rect.size; Paint paint = new Paint(); //Mask Size maskInputSize = Size(mask.width.toDouble(), mask.height.toDouble()); final FittedSizes maskFittedSizes = applyBoxFit(BoxFit.cover, maskInputSize, outputSize); final Size maskSourceSize = maskFittedSizes.source; final Rect maskSourceRect = Alignment.center .inscribe(maskSourceSize, Offset.zero & maskInputSize); canvas.saveLayer(rect, paint); canvas.drawImageRect(mask, maskSourceRect, rect, paint); //Image Size inputSize = Size(image.width.toDouble(), image.height.toDouble()); final FittedSizes fittedSizes = applyBoxFit(BoxFit.cover, inputSize, outputSize); final Size sourceSize = fittedSizes.source; final Rect sourceRect = Alignment.center.inscribe(sourceSize, Offset.zero & inputSize); canvas.drawImageRect( image, sourceRect, rect, paint..blendMode = BlendMode.srcIn); canvas.restore(); } } @override bool shouldRepaint(OverlayPainter oldDelegate) { return mask != oldDelegate.mask || image != oldDelegate.image; } }
Utilisez CustomClipper api.flutter.dev/flutter/rendering/CustomClipper-class.html < / a>
Merci! Cela a fonctionné pour créer la mise en page souhaitée.