Flutter 自定义图片拼贴 完整源代码完整源代码完整源代码:

问题描述

我希望能够构建拼贴,为此我尝试使用 CustomPaint 绘制形状,然后用 image 填充该形状。这是我试过的:

  Container(
    height: 300,width: 300,decoration: Boxdecoration(
      borderRadius: BorderRadius.circular(10.0),border: Border.all(color: Colors.white,width: 5),),child: CustomPaint(
      painter: DrawTriangleShape(color: Colors.blue),child: Image.asset('assets/images/exampleImage.jpg'),

还有我的DrawTriangleShape

class DrawTriangleShape extends CustomPainter {
  Paint painter;

  DrawTriangleShape({color: Colors}) {
    painter = Paint()
      ..color = color
      ..style = PaintingStyle.fill;
  }

  @override
  void paint(Canvas canvas,Size size) {
    var path = Path();

    path.moveto(size.width / 1,0);
    path.lineto(0,size.height);
    path.lineto(size.height,size.width);
    path.close();

    canvas.drawPath(path,painter);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

结果:

enter image description here

正如您所看到的,这并不是真正想要的结果,因为图像没有填充形状。我没有找到任何关于此的信息。甚至有可能吗?如果没有,使用自定义形状构建拼贴画的最佳方法是什么?

如果您需要更多信息,请告诉我!

解决方法

使用 CustomPaint 小部件代替 ClipPath

使用与您的 CustomPaint 相同的路径:

enter image description here

完整源代码

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,title: 'Flutter Demo',home: HomePage(),),);
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ClipPath(
          clipper: CustomClipperImage(),child: Image.asset('images/abstract.jpg'),);
  }
}

class CustomClipperImage extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    return Path()
      ..moveTo(size.width / 1,0)
      ..lineTo(0,size.height)
      ..lineTo(size.height,size.width)
      ..close();
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {
    return false;
  }
}

带有白色边框和缩放图像的附加示例。

enter image description here

完整源代码

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,);
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.of(context).size.width * .8;
    final height = width * .7;
    return Scaffold(
      body: Container(
        color: Colors.black54,child: Center(
          child: Stack(
            children: [
              CustomPaint(
                painter: MyPainter(),child: Container(width: width,height: height),ClipPath(
                clipper: CustomClipperImage(),child: Transform.scale(
                  scale: 3,child: Image.asset('images/abstract.jpg',width: width,],);
  }
}

class CustomClipperImage extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    return Path()
      ..moveTo(size.width,size.height)
      ..close();
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {
    return false;
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas,Size size) {
    final path = Path()
      ..moveTo(size.width,size.height)
      ..close();
    final paint = Paint()
      ..color = Colors.white
      ..strokeWidth = 8.0
      ..style = PaintingStyle.stroke;
    canvas.drawPath(path,paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

对图像进行缩放和平移的解决方案

使用 GestureDetector 检测 scalelocalFocalPoint 的变化。然后使用 Matrix4 Transform 我们的 Image.asset:

enter image description here

完整源代码:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,);
}

class HomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final _width = MediaQuery.of(context).size.width * .8;
    final _height = _width * .6;
    final _zoom = useState<double>(1.0);
    final _previousZoom = useState<double>(1.0);
    final _offset = useState<Offset>(Offset.zero);
    final _previousOffset = useState<Offset>(Offset.zero);
    final _startingFocalPoint = useState<Offset>(Offset.zero);
    return Scaffold(
      body: Container(
        color: Colors.black54,child: Center(
          child: GestureDetector(
            onScaleStart: (details) {
              _startingFocalPoint.value = details.localFocalPoint;
              _previousOffset.value = _offset.value;
              _previousZoom.value = _zoom.value;
            },onScaleUpdate: (details) {
              _zoom.value = _previousZoom.value * details.scale;
              final Offset normalizedOffset =
                  (_startingFocalPoint.value - _previousOffset.value) /
                      _previousZoom.value;
              _offset.value =
                  details.localFocalPoint - normalizedOffset * _zoom.value;
            },child: Stack(
              children: [
                CustomPaint(
                  painter: MyPainter(),child: Container(width: _width,height: _height),ClipPath(
                  clipper: CustomClipperImage(),child: Transform(
                    transform: Matrix4.identity()
                      ..translate(_offset.value.dx,_offset.value.dy)
                      ..scale(_zoom.value),// ..rotateZ(_rotation.value),child: Image.asset('images/milkyway.jpg',width: _width,paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...