Flutter 使图像小部件禁用/变灰

Flutter 使图像小部件禁用/变灰,flutter,Flutter,我有一堆图像小部件,当它们处于禁用状态时,应该是灰色的 有没有办法改变现有图像,使其看起来被禁用/变灰 我希望避免使用启用的图像资源和禁用的图像资源来增加APK的总体大小,而不是使用单个资源。但是,这不可能直接实现。对于运行时灰度,可以使用带颤振的省道。 使用dart图像包加载图像,应用灰度功能,从灰度图像中读取字节,并将其与颤振的image.memorywidget一起使用 您只需获取字节,而无需对彩色图像应用灰度 希望有帮助 根据我个人的经验,我发现将滤色器与不透明度相结合可以很好地使图像处

我有一堆图像小部件,当它们处于禁用状态时,应该是灰色的

有没有办法改变现有图像,使其看起来被禁用/变灰


我希望避免使用启用的图像资源和禁用的图像资源来增加APK的总体大小,而不是使用单个资源。

但是,这不可能直接实现。对于运行时灰度,可以使用带颤振的省道。 使用dart图像包加载图像,应用灰度功能,从灰度图像中读取字节,并将其与颤振的
image.memory
widget一起使用

您只需获取字节,而无需对彩色图像应用灰度


希望有帮助

根据我个人的经验,我发现将滤色器与不透明度相结合可以很好地使图像处于禁用状态

上面显示的是我启用的图像之一的示例

上面显示的是当您应用颜色过滤器并向图像添加不透明度小部件时图像的外观

要实现类似的功能,您需要以下代码:

  new Material(
      elevation: 2.0,
      child: new Opacity(
        opacity: 0.3,
        child: new Container(
          padding: new EdgeInsets.all(20.0),
          child: new Image.asset("assets/<your icon>", fit: BoxFit.cover, color: Colors.grey),
          decoration: new BoxDecoration(
            border: new Border.all(
              width: 2.0, color: const Color(0x40000000)),
              borderRadius: const BorderRadius.all(const Radius.circular(5.0)
            )
          )
        )
      )
  );
新材料(
标高:2.0,
子对象:新的不透明度(
不透明度:0.3,
子容器:新容器(
填充:新边缘设置。全部(20.0),
子项:新图像.asset(“assets/”,fit:BoxFit.cover,颜色:Colors.grey),
装饰:新盒子装饰(
边界:新边界(
宽度:2.0,颜色:常量颜色(0x40000000)),
边界半径:常数边界半径。全部(常数半径。圆形(5.0)
)
)
)
)
);

将小部件设置为容器的子级,并添加如下前台装饰:

Container(
  foregroundDecoration: BoxDecoration(
    color: Colors.grey,
    backgroundBlendMode: BlendMode.saturation,
  ),
  child: child,
)
--更新: 基于Flatter团队的设计,还有另一个小部件。 代码基本相同,如下所示:

ColorFiltered(
  colorFilter: ColorFilter.mode(
    Colors.grey,
    BlendMode.saturation,
  ),
  child: child,
)
const ColorFilter greyscale = ColorFilter.matrix(<double>[
  0.2126, 0.7152, 0.0722, 0, 0,
  0.2126, 0.7152, 0.0722, 0, 0,
  0.2126, 0.7152, 0.0722, 0, 0,
  0,      0,      0,      1, 0,
]);

ColorFiltered(
  colorFilter: greyscale,
  child: child,
);

但我还是更喜欢使用Container ForGroundEdition的方法,因为Container在同一个地方给了您更多的灵活性。

我根据上面的答案创建了一个小部件:

import 'package:flutter/material.dart';

class DisabledRenderer extends StatelessWidget {
  final Widget child;
  final bool enabled;
  final double padding;
  final double boxWidth;
  final Color boxColor;
  final double boxRadius;

  DisabledRenderer(
      {@required this.child,
      @required this.enabled,
      this.padding = 2,
      this.boxWidth = 2,
      this.boxColor = Colors.white,
      this.boxRadius = 5.0});

  @override
  Widget build(BuildContext context) => Material(
        elevation: 2.0,
        child: Opacity(
          opacity: enabled ? 1 : 0.3,
          child: Container(
            padding: EdgeInsets.all(padding),
            child: child,
            decoration: BoxDecoration(
              border: Border.all(width: boxWidth, color: boxColor),
              borderRadius: BorderRadius.all(Radius.circular(boxRadius)),
            ),
          ),
        ),
      );
}
在使用中,它看起来是这样的:

DisabledRenderer(enabled: false, child: Icon(MdiIcons()['speedometer'],);
enable bool通常与StreamBuilder一起用于侦听模型事件。 如何做到这一点,请搜索颤振阵型和StreamBuilder

如果您需要一个支持流(集团模式)的版本,请使用以下版本:

import 'package:flutter/material.dart';

class DisabledRenderer extends StatelessWidget {
  final Widget child;
  final bool enabled;
  final Stream enableStream;
  final double padding;
  final bool showBorder;
  final double boxWidth;
  final Color boxColor;
  final double boxRadius;

  DisabledRenderer(
      {@required this.child,
      this.enabled,
      this.enableStream,
      this.showBorder = true,
      this.padding = 2,
      this.boxWidth = 2,
      this.boxColor = Colors.white,
      this.boxRadius = 5.0}) {
    //one or the other, not both
    assert((enableStream != null && enabled == null) ||
        (enableStream == null && enabled != null));
  }

  @override
  Widget build(BuildContext context) => Material(
        elevation: 2.0,
        child: enableStream != null
            ? StreamBuilder<bool>(
                initialData: false,
                stream: enableStream,
                builder: (BuildContext context, AsyncSnapshot enabled) {
                  return enabled.hasData
                      ? _renderEnabledDisabledState(enabled.data)
                      : Container();
                },
              )
            : _renderEnabledDisabledState(enabled),
      );

  Widget _renderEnabledDisabledState(bool enabled) {
    return IgnorePointer(
      ignoring: !enabled,
      child: Opacity(
        opacity: enabled ? 1 : 0.3,
        child: showBorder
            ? Container(
                padding: EdgeInsets.all(padding),
                child: child,
                decoration: BoxDecoration(
                  border: Border.all(width: boxWidth, color: boxColor),
                  borderRadius: BorderRadius.all(Radius.circular(boxRadius)),
                ),
              )
            : child,
      ),
    );
  }
}

我改编了Mark O'Sullivan post并创建了一个通用小部件:

要使用它:

text = Text("Hellow World");
GrayedOut(text);

班级呢

class GrayedOut extends StatelessWidget {
  final Widget child;
  final bool grayedOut;

  GrayedOut(this.child, {this.grayedOut = true});

  @override
  Widget build(BuildContext context) {
    return grayedOut ? new Opacity(opacity: 0.3, child: child) : child;
  }
}

我认为这可以通过使用alpha来实现,它可以创建禁用的效果。这个技巧也适用于黑暗和光明主题,因为它继承自父主题。我使用了cardColor,您可以选择任何主题并应用颜色

Theme.of(context).cardColor.withAlpha(180)

根据ColorFiltered的颤振文档,您可以使用ColorFilter.matrix,如下所示:

ColorFiltered(
  colorFilter: ColorFilter.mode(
    Colors.grey,
    BlendMode.saturation,
  ),
  child: child,
)
const ColorFilter greyscale = ColorFilter.matrix(<double>[
  0.2126, 0.7152, 0.0722, 0, 0,
  0.2126, 0.7152, 0.0722, 0, 0,
  0.2126, 0.7152, 0.0722, 0, 0,
  0,      0,      0,      1, 0,
]);

ColorFiltered(
  colorFilter: greyscale,
  child: child,
);
const ColorFilter greyscale=ColorFilter.matrix([
0.2126, 0.7152, 0.0722, 0, 0,
0.2126, 0.7152, 0.0722, 0, 0,
0.2126, 0.7152, 0.0722, 0, 0,
0,      0,      0,      1, 0,
]);
彩色滤光(
颜色过滤器:灰度,
孩子:孩子,
);

在这种情况下,ColorFilter将忽略图像的透明区域。

如果您的孩子是.png图像,则如果您将
Colors.grey
放入,则Flatter将以灰色背景渲染它。使用相同颜色的小部件背景,您将有一个完美的禁用图像

ColorFiltered(
    colorFilter: ColorFilter.mode(
        Colors.white,
        BlendMode.saturation,
    ),
    child: child,
)
如果要在用户单击图像时更改图像的颜色,可以执行以下操作:

GestureDetector(

    onTap: () => {

        setState((){

            _active = !_active;

        })
    
    },
    child: ColorFiltered(
    
        colorFilter: _active ? ColorFilter.mode(
                                                                                 
            Colors.transparent,                                                          
            BlendMode.saturation,

        ) : ColorFilter.mode(
                                                                         
            Colors.white,
            BlendMode.saturation,
        ),

        child: Image(

            image: Image.asset("assets/test.png").image
           
        ),
    ),
)

屏幕截图:


代码:

彩色过滤(
colorFilter:colorFilter.mode(
Colors.black.withOpacity(0.5),//0=彩色,1=黑白
BlendMode.saturation,
),
子:Image.asset(
“巧克力图片”,
适合:BoxFit.cover,
),
)

我可以调整浅灰色的灰度值吗?不幸的是,这似乎也会在图像背景上应用过滤器。有办法避免吗?@TinMan检查我在更新部分添加的视频链接。使用image.Asset小部件中的color参数。@当然,您可以将颜色更改为您想要的任何颜色。:)@SinaSeirafi不幸的是,ColorFiltered仍然不能处理透明度:(我不介意人们投票否决一个解决方案。如果你能简单地说明问题是什么,我们都可以从中学习,因为我们在这里做了诚实的努力。谢谢。你的小部件看起来与你的项目相耦合。为什么你的类中存在流?你的代码没有抽象出你项目的复杂性。顺便说一句:否决投票不是我的。它不与我的项目耦合。它是一个通用示例。启用状态可以来自启用布尔或流。流通常用于颤振/飞镖项目。最后一个示例显示了我如何在我的项目中使用它,但小部件本身是通用的。你是对的,你的组件没有真正耦合。它只是感觉很简单ge希望在这种组件中看到一个布尔流,但我看到你也展示了一个简单的布尔。如果你在模型中使用流,你可以直接使用它。没有StreamBuilder等。非常方便。这个解决方案不是OP要求的,它只是包装了一个不透明度小部件。如果你将它应用于彩色图像,它不会变灰,而只是f对于透明图像,这是最简单的方法()。