I have a LeafRenderObjectWidget and want to update my view according to the new widget parameters. for example, I have drawn a line and wish to update the line using scale and don't want to paint it again on the next build.
the problem is in the paint function of RenderObject I have access to PaintingContext but it is not the previous one. so I can't use context.canvas.save() and restore it again in the paint function.
When creating RenderObjects from scratch it's easy to get carried away, but my advice is to not fear repainting. When you call methods on a canvas all it's doing is adding commands to a list that eventually get sent to the raster thread, no actual rendering work is being done here.
It sounds like you are confused on the purpose of canvas.save and canvas.restore. These methods do not save what you painted to the canvas, they only touch the paint transform set by scale, skew, transform and translate.
Related
I am learning and playing around with Flutter. Currently I am trying to reproduce an app I previously made with C# and WPF. In my Flutter app I have a list of Widgets extending CustomPainter. Now I am able to move/drag any of these widgets around the screen. What I see is that always when dragging one of this widgets all CustomPaint widgets are repainted. I checked what would happen if I decide to resize my window, and you can guess, all CustomPaint widgets are repainted.
I decided to create three different projects. One is using statefull widgets and setState to manage the state. The other is using Provider and the last one is using Riverpod. Still all Widgets extending CustomPainter are repainted when dragging a single Widget or resizing the window.
Now my question is, am I doing something wrong in my state management or is this behavior by default?
Also my C#/WPF app uses half the cpu the Flutter app uses when dragging one shape around. I did not expect such a difference. For now I did not make any complex CustomPaint obecjt in my flutter app. But should I expect a big performance reduction if I have many complex CustomPaint widgets?
am I doing something wrong in my state management or is this behavior
by default?
Yes and no. Widgets are rebuilt when the screen size changes, but dragging a widget should not make other widgets rebuild. You can try RepaintBoundary (https://api.flutter.dev/flutter/widgets/RepaintBoundary-class.html)
Should I expect a big performance reduction if I have many complex
CustomPaint widgets?
This has a lot to do with what kind of CustomPaint widgets you will be using and what is "many". You can test how long the CustomPaint widget's paint method takes, for example by using the profiler (https://docs.flutter.dev/perf/ui-performance). My assumption is that the efficiency decreases linearly as you add more CustomPaint widgets
I'm trying to make an Alphabet Tracing App Logic is Almost clear
1- I made proper path using Custom Clipper so user can only touch inside the Path
2- I made Custom Paint as child of Custom Clipper so user can draw inside it
3- But there is an issue in this logic user can draw in whole Alphabet but requirements are slightly different. I want to draw some portion first and other portion after that how can I do that any Idea ? For Reference I am Uploading an Image you can check it as well
I'm painting two layers of graphs on one CustomPaint. The first will occlude over half of the second layer.
Problem
Currently I just paint the first data and then second data using two Paints, with their blendMode set.
This creates an overlay of two data, which blends. But I don't need the blend, just the area of difference to be painted using the second Paint, i.e., a complementary composite view.
On the performance side, I don't know if blending would have internal optimization to avoid drawing the occluded part.
Reference image
Notice that all these data graphs blend but I just need them to occlude each other, while the overlapped parts don't draw at all for performance.
Attempts
I could use a new path to only draw the difference, but I'm not sure this is the easiest way.
I checked RepaintBoundary but it's a widget that handles infrequent data changes, not exactly what I need here.
Similarly Overlay seems a standalone widget, so I don't know how to fit it into CustomPaint.
Question
Is there a standard way to achieve the occlusion I need?
I have an image in one page of the PageView. I want to animate this image to the next page when i go to it, sort of like when you use Hero animations in navigator page transitions. Any ideas how this can be achieved?
In order to achieve an animation similar to the hero animation. Basically what we will implement is this, you will need 5 elements:
The initial global coordinates
The final coordinates
Initial widget size
Final widget size
The widget you want to animate
Now in order to create this animation that spans the 2 screens we will need to use the overlay that is present in flutter. link
Add to the Overlay the widget that is to be animated (Not the widget present on the screen, a new instance).
Position this overlay entry to be in the starting coordinate of the animation (The original widget's position).
Hide the original widget.
Create an animation that changes the x and y coordinates to the create the custom motion, this can be any curve, the simplest being a simple tween between the starting coordinate and the end coordinate.
Another animation that animates size change between the start and end size. This animation can be combined with the previous one. (One tween animation but the values are calculated manually)
After the animation is done, remove the overlay entry, and show the new widget. (This can be done as a timed operation or as a call back operation)
This is the most flexible between all of the available options since you have access to the widget in all of its states. However you must be very careful when using this method as it might cause a slowdown if not properly implemented.
This packages does what you want https://pub.dev/packages/coast
It is essentially taking the same approach as Flutter’s Hero and HeroController: Detect when a transition is started, search through the element trees of the source and target pages for the widgets marked for animation (heroes, crabs), pair them up based on their tags, and finally create an entry in an Overlay whose position and size is the interpolation between those on the source and target pages.
I have wary annoying problem with dnd dragging image. When I start dragging some widget, it shows some default icon as it moves. I just want that this icon is actually widget looks itself. So it should look just as I move widget by dragging.
Is there easy way to accomplish this?
I started to look around and all I found is to set image using pixbuf
pixbuf = gtk.gdk.pixbuf_new_from_xpm_data(xpm)
myWidget.drag_source_set_icon_pixbuf(pixbuf)
This way it works, but I need to use current looks of widget, because there are themes and overlay of few images.
You can get the Cairo context of the widget, then copy it to a pixbuf:
cr = widget.window.cairo_create()
surface = cr.get_target()
surface.write_to_png('test.png')
pixbuf = gtk.gdk.pixbuf_new_from_file('test.png')
context.set_icon_pixbuf(pixbuf, 0, 0)
Here I'm going through an intermediary file to save and load the image data. There's probably a direct way to do that, but after going through the Cairo documentation and trying out various weird things, I gave up.