Flutter在Container设置渐变填充后Ink.image图片无法显示

1、环境版本

        Flutter版本:3.16.9

        开发IDE:android studio 2023.2.1 

        以下代码在Android中测试通过,iOS没有试过。以后升级啥的可能会和本方案会有出入,请自行甄别。

2、Ink.image图片无法显示场景

        当对Container做了LinearGradient渐变填充后,在其child中添加子Widget中包含lnk.image类型的图片按钮,会导致图片无法正常显示,但按钮还可以正常点击的情况,同时点击按钮也不会触发InkWell的水墨效果。

class _TestPageState extends State<TestPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      body: Column(
        children: [
          Container(
            width: double.infinity,
            padding: const EdgeInsets.only(top: 90),
            decoration: const BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                colors: [
                  Color.fromRGBO(21, 169, 113, 1.0),
                  Colors.white,
                  Colors.white,
                ],
              ),
            ),
            child: Column(
              children: [
                const SizedBox(height: 30,),
                Ink.image(
                  width: 60,
                  height: 60,
                  image:
                  const AssetImage(Assets.imagesIIconReport), //特定页面中调用会加载不出图片
                  onImageError: (Object exception, StackTrace? stackTrace) {
                    debugPrint("加载图片异常了!!!!!");
                  },
                  fit: BoxFit.fill,
                  child: InkWell(
                    borderRadius: const BorderRadius.all(Radius.circular(50.0)),
                    autofocus: true,
                    onTap: () {
                      print("点击");
                    },
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

        运行后的效果如下图:

3、解决方案

        这问题其实很容易解决,(未深入分析问题产生原因,个人猜测问题产生的原因)它的问题是出在Container在填充渐变背景色时和Ink.image中绘图产生了覆盖,填充的渐变背景色显示层级高于包含在内的Ink.image的图片,导致把图片覆盖后产生看不到的原因,但如果为图片按钮添加文字则文字是能正常显示。这个问题当是困扰了我很久,如果文字也不显示那还好说,立马能想到这个覆盖问题。只要把上面代码的填充最后一项颜色变成透明色就可以解决(当然也要取决于你图标按钮显示的位置,需要处在透明色区域)

              gradient: LinearGradient(
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                colors: [
                  Color.fromRGBO(21, 169, 113, 1.0),
                  Colors.white,
                  //Colors.white,
                  Color.fromRGBO(255, 255, 255, 0),
                ],
              ),

        效果如下图:

        这大概可能是一个底层绘图BUG吧。

您可以使用`flutter`中的`paint`来将图片渲染为圆形图片。以下是示例代码: ```dart class CircleImage extends StatelessWidget { final String imageUrl; final double size; const CircleImage({Key key, this.imageUrl, this.size}) : super(key: key); @override Widget build(BuildContext context) { return CustomPaint( size: Size(size, size), painter: CircleImagePainter(imageUrl), ); } } class CircleImagePainter extends CustomPainter { final String imageUrl; CircleImagePainter(this.imageUrl); @override void paint(Canvas canvas, Size size) async { final image = await _loadImage(imageUrl); final paint = Paint() ..shader = ImageShader( image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage, ); final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2; canvas.drawCircle(center, radius, paint); } @override bool shouldRepaint(CircleImagePainter oldPainter) => oldPainter.imageUrl != imageUrl; Future<ui.Image> _loadImage(String imageUrl) async { final image = NetworkImage(imageUrl); final completer = Completer<ui.Image>(); image.resolve(ImageConfiguration()).addListener( ImageStreamListener( (imageInfo, _) => completer.complete(imageInfo.image), ), ); return await completer.future; } } ``` 在上述代码中,我们自定义了一个`CircleImage`组件,它接受一个`imageUrl`和`size`参数。在组件中,我们使用了`CustomPaint`来绘制圆形图片。我们创建了一个自定义的`CircleImagePainter`来实现`CustomPainter`,在`paint`方法中,我们首先通过`_loadImage`方法加载图片,然后使用`ImageShader`将图片渲染到圆形区域内,最后使用`drawCircle`方法绘制圆形。 需要注意的是,为了避免重复加载图片,我们在`shouldRepaint`方法中对`imageUrl`进行了比较,如果新的`imageUrl`与旧的不同,才会重新加载图片。 希望以上信息能够对您有所帮助。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值