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.