使 BoxDecoring 图像褪色/透明

我有以下代码片段,我想使图像褪色,以便它不干扰容器中的其他项目。 有没有什么过滤器可以做到这一点?

child: new Card(
child: new Container(
decoration: new BoxDecoration(
color: const Color(0xff7c94b6),
image: new DecorationImage(
image: new ExactAssetImage('lib/images/pic1.jpg'),
)
)
)
)
109455 次浏览

你可以给你的 DecorationImage一个 ColorFilter使背景图像灰色(使用 saturation颜色过滤器)或半透明(使用 dstATop颜色过滤器)。

screenshot

此示例的代码如下。

import 'package:flutter/material.dart';


void main() {
runApp(new MyApp());
}


class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage(),
);
}
}


class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) => new Scaffold(
appBar: new AppBar(
title: new Text('Grey Example'),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
new Card(
child: new Container(
child: new Text(
'Hello world',
style: Theme.of(context).textTheme.display4
),
decoration: new BoxDecoration(
color: const Color(0xff7c94b6),
image: new DecorationImage(
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
image: new NetworkImage(
'http://www.allwhitebackground.com/images/2/2582-190x190.jpg',
),
),
),
),
),
],
),
);
}

Opacity小部件是另一种选择。

您还可以预先将效果应用于资产。

您可以简单地使用一个 Stack 小部件,并在图像上方使用一个简单的彩色容器,以减少不透明度。

例如:enter image description here

        import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';


import './page2.dart';
import './page3.dart';
import './page4.dart';


void main() {
debugPaintSizeEnabled = true ;
return runApp(Start());
}


class Start extends StatelessWidget {


@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'InIt',
home: Builder(builder: (context) {
return GestureDetector(
onTap: () {
return Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return Page2();
},
),
);
},
child: Scaffold(
body: Stack(
children: <Widget>[


Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/page1.jpg'),
fit: BoxFit.fitHeight),
),
),
Container(
color: Color.fromRGBO(255, 255, 255, 0.19),
),
Container(
alignment: Alignment.center,
child: Center(
child: Text(
'LETS BE PRODUCTIVE TODAY',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 50.0,
fontFamily: 'bold',
fontWeight: FontWeight.bold,
color: Color.fromRGBO(255, 255, 255, 1)),
),
),
),
Container(
margin: EdgeInsets.only(bottom: 10.0),
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {},
constraints:
BoxConstraints.tightFor(height: 10.0, width: 10.0),
shape: CircleBorder(),
fillColor: Colors.white,
),
Page2call(),
Page3call(),
Page4call(),
],
),
)
],
),
),
);
}),
);
}
}


class Page2call extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return RawMaterialButton(
onPressed: () {
return Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return Page2();
},
),
);
},
constraints: BoxConstraints.tightFor(height: 10.0, width: 10.0),
shape: CircleBorder(),
fillColor: Colors.white,
);
}
}


class Page3call extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return RawMaterialButton(
onPressed: () {
return Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return Page3();
},
),
);
},
constraints: BoxConstraints.tightFor(height: 10.0, width: 10.0),
shape: CircleBorder(),
fillColor: Colors.white,
);
}
}


class Page4call extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return RawMaterialButton(
onPressed: () {
return Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return Page4();
},
),
);
},
constraints: BoxConstraints.tightFor(height: 10.0, width: 10.0),
shape: CircleBorder(),
fillColor: Colors.white,
);
}
}

这是一个完全实现的例子,你可以在这里增加不透明度 为了让背景变得更加模糊,第四个理由是不透明:

Container(
color: Color.fromRGBO(255, 255, 255, 0.19),
),

这种方法也使你能够选择衰落滤波器的颜色。

你可以简单地使用

ColorFiltered(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
child: YourWidget(),
)

对于那些想知道 < strong > 性能 是否可以(因为图像和不透明度都是资源密集型的东西)的人,这里是我对文档和源代码的挖掘和答案。

结论: 使用 DecorationImage(colorFilter: ...)将是正式文件建议的 一样快。(但 OpacityColorFilter小部件不是)

首先,我们应该 没有使用 OpacityColorFilter小部件,因为它可以触发 saveLayer和昂贵的(由 官方文件)。

相反,我们 应该

仅在必要时使用不透明小部件。有关直接将不透明度应用于图像的示例,请参见不透明度 API 页面中的透明图像部分,这比使用不透明度小部件更快。

查看建议的 方法,我们看到以下样本:

Image.network(
'https://raw.githubusercontent.com/flutter/assets-for-api-docs/master/packages/diagrams/assets/blend_mode_destination.jpeg',
color: Color.fromRGBO(255, 255, 255, 0.5),
colorBlendMode: BlendMode.modulate
)

现在的问题是,这个得到高度评价的答案,也就是下面的代码,是否和官方文档中提到的 Image小部件一样快?

Container(
child: Text('hi'),
decoration: BoxDecoration(
color: const Color(0xff7c94b6),
image: new DecorationImage(
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
image: new NetworkImage(
'http://www.allwhitebackground.com/images/2/2582-190x190.jpg',
),
),
),
),

为了回答这个问题,让我们看看 Image.network的源代码。这个构造函数将直接填充 ImagecolorBlendMode字段。

Imagebuild,它将是 直接传递到 RawImagecolorBlendMode领域。

然后,RawImage将创建 RenderImage(一个 RenderObject)并更新 RenderImage._colorBlendMode

接下来,请注意 RenderImage 如何处理这个-

  BlendMode? _colorBlendMode;
set colorBlendMode(BlendMode? value) {
if (value == _colorBlendMode)
return;
_colorBlendMode = value;
_updateColorFilter();
markNeedsPaint();
}


...


/// If non-null, this color is blended with each image pixel using [colorBlendMode].
Color? get color => _color;
Color? _color;
set color(Color? value) {
if (value == _color)
return;
_color = value;
_updateColorFilter();
markNeedsPaint();
}


...


ColorFilter? _colorFilter;
void _updateColorFilter() {
if (_color == null)
_colorFilter = null;
else
_colorFilter = ColorFilter.mode(_color!, _colorBlendMode ?? BlendMode.srcIn);
}

更深入地研究 rendering/image.dart将会发现,除了创建这个 _colorFilter之外,colorBlendMode(和 _colorBlendMode将不会在其他地方使用。

因此,我们知道 Image.network的两个参数最终将进入 RenderImage._colorFilter

事实上,_colorFilter将在 RenderImage.paint中作为

  @override
void paint(PaintingContext context, Offset offset) {
...
paintImage(
canvas: context.canvas,
rect: offset & size,
image: _image!,
colorFilter: _colorFilter,
...
);
}

这么说我们知道了!它将在与本机方法通信的 paintImage中使用。难怪它比 Opacity快。

不回到我们的 DecorationImage。在 painting/decoration_image.dart,我们看到 DecorationImagePainter:

class DecorationImagePainter {
DecorationImagePainter._(this._details, ...);


final DecorationImage _details;


void paint(Canvas canvas, Rect rect, Path? clipPath, ImageConfiguration configuration) {
...
paintImage(
canvas: canvas,
rect: rect,
image: _image!.image,
colorFilter: _details.colorFilter,
...
);
}
}

嘿,这是完全一样的!

使用 不透明等级。 使其子级部分透明的小部件。

Opacity(
opacity: 0.5,
child: Image.asset('images/lion.png'),
)