In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "what is the solution of embedding Native components in Flutter". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
1. Use tutorial 1.1. DemoRun
The scene of embedding a map may exist in many App, but the current map SDK does not provide a library of Flutter, and it is obviously not realistic to develop your own set of maps. In this scenario, using the form of hybrid stack is a better choice. We can embed a Map directly in the drawing tree of Native, but the View embedded in this solution is not in the drawing tree of Flutter, so it is a more violent and unelegant way, and it is very difficult to use.
At this point, using AndroidView, the official control provided by Flutter, is a more elegant solution. Here we have made a simple demo embedded in Amap. Let's follow this application scenario and take a look at the use and implementation principle of AndroidView.
1.2. How AndroidView is used
AndroidView is used in a way similar to MethodChannel, which is relatively simple, and is mainly divided into three steps:
Step 1: use AndroidView in the appropriate place in the dart code, and you need to pass in a viewType, which will be used to uniquely identify the Widget and to associate with the View of the Native.
Step 2: add code to the native side. The main task of writing a PlatformViewFactory,PlatformViewFactory is to create a View in the create () method and pass it to Flutter. (this is not accurate, but we can understand it this way, which will be explained later.)
Step 3: use the registerViewFactory () method to register the newly written PlatformViewFactory, which requires passing in two parameters, the first parameter corresponding to the viewType written on the fluter side, and the second parameter being the newly written PlatformViewFactory.
The part of configuring Amap will be omitted here. There are more detailed official documents, which can be checked on the Gaode developer platform.
These are all the operations of using AndroidView. On the whole, it looks relatively simple, but there are still two problems that can not be ignored if you really want to use it:
Who decides the final display size of the View?
How is the touch event handled?
two。 Principle explanation
In order to solve the above two problems, we must first understand the nature of the so-called "View".
2.1. What is the essence of the so-called "View"?
To solve this problem, it is inevitable to read the source code. If you look at the whole process of transmission from a deeper level, you can sort out a flow chart like this:
As we can see, what Flutter finally gets is a textureId returned by the native layer. According to the knowledge of native, ky h this textureId is the ID corresponding to the drawing data of the view that has been rendered on the native side. Through this ID, you can directly find the corresponding drawing data in GPU and use it, so how does Flutter make use of this ID?
In the previous in-depth understanding of Flutter interface development, we also introduced the drawing process of Flutter. Let me sort it out briefly for you here, too.
The Framework layer of Flutter will finally submit a layerTree to the Engine layer, and each leaf node in the pipeline will traverse every leaf node of layertree, and each leaf node will eventually call the Skia engine to complete the drawing of interface elements. After traversing, press glPresentRenderBuffer (IOS) or glSwapBuffer (Android) to complete the screen operation.
There are many kinds of Layer, and AndroidView uses TextureLayer among them. TextureLayer is described in more detail in the previous "Flutter external texture", so I won't repeat it here. When TextureLayer is traversed, it calls a method in the engine layer, SceneBuilder::addTexture (), to pass in textureId as an argument. Finally, when drawing, skia will find the corresponding drawing data directly in GPU according to textureId, and draw it to the screen.
So is it possible for anyone who gets this ID to do this? The answer is, of course, no. The Texture data is stored in the thread corresponding to the EGLContext that created it, so you can't get the corresponding data if you operate on another thread. Several concepts need to be introduced here:
Display object (Display): provides information about reasonable pixel density and size of the display
Presentation: it provides Android with the ability to draw on the corresponding context (Context) and display object (Display), usually for dual-screen display.
Instead of explaining Presentation here, we just need to understand that Flutter realizes the external texture through Presentation. When creating Presentation, pass in the Context corresponding to FlutterView and a virtual display object created, so that Flutter can find and use the texture data created by Native directly through ID.
2.2. Who decides the final display size of the View?
As you can imagine from the above process, the display size seems to be determined by two parts: the size of the AndroidView and the size of the View on Android. So who is actually going to decide? let's do an experiment.
Create a new Flutter project directly and change the middle to an AndroidView.
/ / Flutterclass _ MyHomePageState extends State {double size = 200.0; void _ changeSize () {setState (() {size = 100.0;}) @ override Widget build (BuildContext context) {return new Scaffold (appBar: new AppBar (title: new Text (widget.title),), body: Container (color: Color (0xff0000ff), child: SizedBox (width: size, height: size, child: AndroidView (viewType: 'testView',)) FloatingActionButton: new FloatingActionButton (onPressed: _ changeSize, child: new Icon (Icons.add),) }}
The corresponding code should also be added on the Android side. In order to better see the effect of cutting, ImageView is used here.
/ / Android@Overridepublic PlatformView create (final Context context, int I, Object o) {final ImageView imageView = new ImageView (context); imageView.setLayoutParams (new ViewGroup.LayoutParams (500500)); imageView.setBackground (context.getResources (). GetDrawable (R.drawable.idle_fish)); return new PlatformView () {@ Overridepublic View getView () {return imageView @ Override public void dispose () {}};}
First of all, the RenderObject corresponding to AndroidView,AndroidView is RenderAndroidView, and there are two possibilities to determine the final size of a RenderObject, one is specified by the parent node, and the other is to determine the size according to its own conditions in the range specified by the parent node. Open the corresponding source code, you can see that there is a very important attribute sizedByParent = true, that is, the size of the AndroidView is determined by its parent node, we can use Container, SizedBox and other controls to control the size of the AndroidView.
The drawing data for AndroidView is provided by the Native layer, so what happens when the actual pixel size of the View rendered in Native is larger than the size of AndroidView? Usually, there are only two options to deal with this situation, one is cropping, the other is zooming. Flutter maintains its consistent practice, and all out of the bounds Widget is presented in a tailored manner, and the situation described above is treated as an out of the bounds.
When the actual pixel size of the View is smaller than the AndroidView, you will find that the View will not become smaller accordingly (the background color of the Container is not exposed), and the areas without content will be filled with white. The reason for this is that a FrameLayout is used as the rootView in SingleViewPresentation::onCreate.
2.3. How touch events are transmitted
The event flow of Android should be familiar to everyone, passing from top to bottom, processing from bottom up, or backflow. Flutter uses the same rule, but AndroidView handles gestures through two classes:
MotionEventsDispatcher: responsible for encapsulating events into Native events and passing them to Native
AndroidViewGestureRecognizer: responsible for recognizing the corresponding gesture, which has two attributes:
CachedEvents and forwardedPointers will be distributed only if the pointer attribute of PointerEvent is in forwardedPointers, otherwise it will be stored in cacheEvents. The implementation here is mainly to resolve the conflicts of some events, such as sliding events, which can be handled through gestureRecognizers. You can refer to the official comments here.
/ For example, with the following setup vertical drags will not be dispatched to the Android view as the vertical drag gesture is claimed by the parent [GestureDetector]. / onVerticalDragStart: (DragStartDetails d) {}, / / child: AndroidView (/ viewType: 'webview',/// gestureRecognizers: [], /) /) / To get the [AndroidView] to claim the vertical drag gestures we can pass a vertical drag gesture recognizer in [gestureRecognizers] e.g:/// GestureDetector (/ / onVerticalDragStart: (DragStartDetails d) {}, / child: SizedBox (/ width: 200.0 height) / height: 100.0 viewType SizedBox / child: AndroidView (/ viewType: 'webview' / gestureRecognizers: [new VerticalDragGestureRecognizer ()], /) "what is the solution to embedding Native components in Flutter?" that's it. Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.