Preface:
This is the seventh day of my participation in the August More text Challenge. For details, see: August More Text Challenge. To prepare for the August challenge of the nuggets, I’m going to pick 31 components this month that haven’t been introduced before and do a full analysis and attribute introduction. These articles will be used as important material in the collection of the Flutter components. I hope I can stick to it, your support will be my biggest motivation ~
- 1. [Flutter component collection] NotificationListener | August more text challenge
- 2.【Flutter Components 】Dismissible | August more challenges
- 3.【Flutter Component Collection 】 How the Switch was made | August More text Challenge
- 4.【Flutter Component Collection 】Scrollbar | August more text challenge
- 5. ClipPath | August
- 6. The Flutter components checked 】 CupertinoActivityIndicator | August more challenges
- 7.【Flutter component collection 】Opacity | August more text challenge
[this article]
1. Understand the Opacity component
The Opacity component is defined in the Widget/Basic. dart in the framework, indicating that it is a more basic component. The function is to set a component to be transparent by specifying opacity opacity.
1. Basic information on Opacity
Below is the Opacity of the component class definition and construction method, it can be seen that it inherited from SingleChildRenderObjectWidget. When instantiating, you must pass in the opacity parameter, and you can also pass in a ChuILD component.
The Opacity component is simple and easy to use. In addition, there are other ways to make widgets transparent, such as setting the alpha value of the color. What are the pros and cons of using the Opacity component, what is the necessity, and when and when not to use it? In this article, you’ll revisit the Opacity component from the perspective of source code, giving you a more comprehensive view of Opacity.
2. The use of Opacity
The following is the Opacity effect of 0.1 at an interval of 0.1 to 0.8.
class OpacityTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 10,
runSpacing: 20,
children: [0.1.0.2.0.3.0.4.0.5.0.6.0.7.0.8]
.map((opacity) => Opacity(
opacity: opacity,
child: Image.asset(
'assets/images/icon_head.webp',
width: 80,
height: 80, ), )) .toList(), ); }}Copy the code
3. Color-based transparency
The Opacity of an image can be achieved using color + colorBlendMode, which has the same effect as Opacity.
class OpacityTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 10,
runSpacing: 20,
children: [0.1.0.2.0.3.0.4.0.5.0.6.0.7.0.8]
.map((opacity) =>
Image.asset(
'assets/images/icon_head.webp',
width: 80,
height: 80,
color: Color.fromRGBO(255.255.255, opacity), colorBlendMode: BlendMode.modulate ), ) .toList(), ); }}Copy the code
What’s the difference between these two approaches? Before you do that, take a look at how the source code for Opacity is implemented.
2. Source implementation of Opacity
1. Properties of the Opacity component
The primary property of Opacity is double-type Opacity, and a child component can be passed in. As shown by the assertion, opacity cannot be empty, and the value ranges from 0.0 to 1.0.
2. RenderObject maintained by Opacity
Opacity inherited from SingleChildRenderObjectWidget, as RenderObjectWidget gens, has to create and maintain RenderObject mission.
Opacity#createRenderObject returns opacity, which means that the implementation of transparency is completed by the RenderOpacity object. Opacity is a component that serves only as a configuration function.
3. Know RenderOpacity
RenderObject is the offspring of RenderObject, namely, a RenderObject, which is responsible for layout and rendering. The _alpha member is initialized in the constructor based on the opacity passed in.
GetAlphaFromOpacity is a static method of the Color class, which converts the opacity of 0 ~ 1 to an alpha value of 0 ~ 255.
---->[Color#getAlphaFromOpacity]----
static int getAlphaFromOpacity(double opacity) {
assert(opacity ! =null); // ignore: unnecessary_null_comparison
return (opacity.clamp(0.0.1.0) * 255).round();
}
Copy the code
4. RenderOpacity# paint method
The most important thing is the processing of rendering. The following is the logic of RenderOpacity#paint. As you can see, when the child is not empty, if _alpha = 0 then you don’t have to draw anything, you just return. If _alpha = 255, the child is drawn directly.
Setting Opacity to 0 not only preserves the placeholder of the child component, but also avoids drawing the child, which is a good way to hide the component. If you do not need a placeholder, it is better to pass if, and if you do need a placeholder, Opacity will be better. Comparison with if requires a placeholder component in the else.
Finally, transparency, if available, is handled through context.pushopacity. So what does the pushOpacity method do?
PaintingContext#pushOpacity
1. Debug breakpoints
Let’s see what happens at run time with a minimal demo.
void main() => runApp(OpacityTest());
class OpacityTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Opacity(
opacity: 0.3,
child: Image.asset(
'assets/images/icon_head.webp',
width: 80,
height: 80)); }}Copy the code
The breakpoint information is shown below. The left stack frame shows how the method pushes when a frame is drawn to RenderOpacity#paint. RenderObject has a containerLayer-type _layer property, which defaults to null. The next step is to execute context.pushOpacity. Here the context object type is PaintingContext, _alpha = 77, oldLayer = null.
After PaintingContext#pushOpacity is pushed, if oldLayer is empty, the OpacityLayer is created, alpha and offset are set for it, and the pushLayer method is executed.
If the childLayer has children, it will remove its children, so the OpacityLayer that we just created here, without children, won’t go into the if code block.
The OpacityLayer created by the process is then added to the _containerLayer with appendLayer.
2. Synthesis of layers
When the flushLayout, flushCompositingBits, and flushPaint in the drawFrame are complete, no content will appear on the screen. Also need through renderView.com positeFrame () to transfer data to the GPU.
After the processing of the previous method, both the element tree and the render tree are formed. The renderView object, the topmost node in the render tree, compositeFrame. RenderView’s Layer is the TransformLayer. It also has child and parent properties, forming a tree structure.
The layer above has only two nodes, the TransformLayer and its child OpacityLayer. Then execute layer! .buildScene(Builder), create the uI.scene object.
The addToScene method tells the child to do addToScene, so all the layers are added to the Scene.
3. ui.Scene
The purpose of the
By calling the buildScene method with the TransformLayer held in the renderView, we can merge all the layers below it into a Scene and return the uI. Scene object, Finally, the ui.Scene object is rendered using the _window.render method.
The rendering method is a platform native method. All in all, using the Opacity component is ultimately transparency through an OpacityLayer.
Fourth, look at the advantages and disadvantages of Opacity
The Opacity component is implemented directly using the OpacityLayer, which adds one more layer to the frame, which is slightly more expensive but valuable. Opacity using color has its limits, and some transparencies must be made on the Opacity component. If it’s Image or Color that needs to be transparent, then you don’t have to do anything about it.
However, when an entire item or page needs to be transparent, using the Opacity component is convenient and simple. Otherwise you need to make all the colors transparent. Doing so makes the code complex and unreadable, and it may make it impossible for objects to remain const, such as a const Text(“XXX”). To make the color transparent, you need to define the color using Texstyle. This transparency needs to be obtained at runtime, so the Text cannot remain const, and there is more code for style handling.
The Layer hierarchy is also designed to be used. One more Layer, that is, more methods in the stack of composition, is not as heavy as imagined. Therefore, Opacity should be used, but it is not necessary to use Opacity on a single image or color.
Widget buildItem() {
return Container(
height: 80,
margin: const EdgeInsets.all(10),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: BorderRadius.circular(10)
),
child: Row(
children: [
const SizedBox(width: 15),
Image.asset(
'assets/images/icon_head.webp',
width: 60,
height: 60,),const SizedBox(width: 15,),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text( 'Zhang Feng Jiete Li',
style: TextStyle(fontSize: 16),),const Text( 'The King of Programming',
style: TextStyle(fontSize: 14,color: Colors.grey),
),
],
),
const Spacer(),
const Icon(Icons.ac_unit_outlined, color: Colors.blue , size: 24),
const SizedBox(width: 5,),
const Icon(Icons.alt_route_rounded, color: Colors.blue , size: 24,),
const SizedBox(width: 20,),),); }Copy the code
Someone might be tempted to say “ColorFiltered”, instead of “ColorFiltered”. When you take a look at the ColorFiltered source code, you’ll see that it also works by adding a ColorFilterLayer, so it’s self-defeating.
Once you know all this, you will have a comprehensive understanding of the Opacity component, whether it is good or not, but whether it is a good or bad tool to use. When using, just pay attention to it and ask, “Can I easily achieve transparency through color transparency?” If yes, do not use Opacity; conversely, use it. Also, don’t forget the advantages of Opacity over a single component. That’s all for this article. Thanks for watching
The following explains how to use the Opacity component. Although it is a simple widget, there are a few things we can learn from the implementation of the source code. That’s the end of this article. Thanks for watching. See you tomorrow