返回顶部
首页 > 资讯 > 精选 >在Flutter中嵌入Native组件的解决方法是什么
  • 445
分享到

在Flutter中嵌入Native组件的解决方法是什么

2023-06-04 21:06:49 445人浏览 安东尼
摘要

本篇内容介绍了“在Flutter中嵌入Native组件的解决方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 使用教程1.1.

本篇内容介绍了“在Flutter中嵌入Native组件的解决方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1. 使用教程

1.1. DemoRun

嵌入地图这一场景可能在很多App中都会存在,但是现在的地图SDK都没有提供Flutter的库,而自己开发一套地图显然不太现实。这种场景下,使用混合栈的形式是一个比较好的选择。我们可以直接在Native的绘图树中嵌入一个Map,但是这个方案嵌入的View并不在Flutter的绘图树中,是一种比较暴力且不优雅的方式,使用起来也很费劲。

这时候,使用Flutter官方提供的控件AndroidView就是一种比较优雅的解决方案了。这里做了一个简单的嵌入高德地图的demo,就让我们跟着这个应用场景,看一下AndroidView的使用方式和实现原理。

在Flutter中嵌入Native组件的解决方法是什么

1.2. AndroidView使用方式

AndroidView的使用方式和MethodChannel类似,比较简单,主要分为三个步骤:

dart代码的相应位置使用AndroidView,使用时需要传入一个viewType,这个String将用于唯一标识该Widget,用于和Native的View建立关联。

在Flutter中嵌入Native组件的解决方法是什么

在native侧添加代码,写一个PlatfORMViewFactory,PlatformViewFactory的主要任务是,在create()方法中创建一个View并把它传给Flutter(这个说法并不准确,但是我们姑且可以这么理解,后续会进行解释)

在Flutter中嵌入Native组件的解决方法是什么

使用reGISterViewFactory()方法注册刚刚写好的PlatformViewFactory,该方法需要传入两个参数,第一个参数需要和之前在Flutter端写的viewType对应,第二个参数是刚刚写好的的PlatformViewFactory。

在Flutter中嵌入Native组件的解决方法是什么

配置高德地图的部分这里就省略不说了,官方有比较详细的文档,可以去高德开发者平台进行查阅。

以上便是使用AndroidView的所有操作,总体看起来还是比较简单的,但是真正要用起来,还是有两个无法忽视的问题:

  1. View最终的显示尺寸由谁决定?

  2. 触摸事件是如何处理的?

2. 原理讲解

想要解决上面的两个问题,首先必须得理解所谓"传View"的本质是什么?

2.1. 所谓"传View"的本质是什么?

要解决这个问题,自然避免不了的需要去阅读源码,从更深的层面去看这个传递的整个过程,可以整理出一张这样的流程图:

在Flutter中嵌入Native组件的解决方法是什么

我们可以看到,Flutter最终拿到的是native层返回的一个textureId。根据native的知识ky h这个textureId是已经在native侧渲染好了的view的绘图数据对应的ID,通过这个ID可以直接在GPU中找到相应的绘图数据并使用,那么Flutter是如何去利用这个ID的呢?

在之前的深入了解Flutter界面开发中,也给大家介绍了Flutter的绘图流程。我这里也给大家再简单整理一下

在Flutter中嵌入Native组件的解决方法是什么

Flutter的Framework层最后会递交给Engine层一个layerTree,在管线中会遍历layertree的每一个叶子节点,每一个叶子节点最终会调用Skia引擎完成界面元素的绘制,在遍历完成后,在调用glPresentRenderBuffer(iOS)或者glSwapBuffer(Android)按完成上屏操作。

Layer的种类有很多,而AndroidView则使用的是其中的TextureLayer。TextureLayer在之前的《Flutter外接纹理》中有更为详细的介绍,这里就不再赘述。TextureLayer在被遍历到时,会调用一个engine层的方法SceneBuilder::addTexture() 将textureId作为参数传入。最终在绘制的时候,skia会直接在GPU中根据textureId找到相应的绘制数据,并将其绘制到屏幕上。

那么是不是谁拿到这个ID都可以进行这样的操作呢?答案当然是否定的,Texture数据存储在创建它的EGLContext对应的线程中,所以如果在别的线程进行操作是无法获取到对应的数据的。这里需要引入几个概念:

  • 显示屏对象(Display):提供合理的显示器的像素密度和大小的信息

  • Presentation:它给Android提供了在对应的上下文(Context)和显示屏对象(Display)上绘制的能力,通常用于双屏异显。

这里不展开讲解Presentation,我们只需要明白Flutter是通过Presentation实现了外接纹理,在创建Presentation时,传入FlutterView对应的Context和创建出来的一个虚拟显示屏对象,使得Flutter可以直接通过ID找到并使用Native创建出来的纹理数据。

2.2. View最终的显示尺寸由谁决定?

通过上面的流程大家应该都能想到,显示尺寸看起来像是由两部分决定的:AndroidView的大小,Android端View的大小。那么实际上到底是有谁来决定的呢,让我们来做一个实验?

直接新建一个Flutter工程,并把中间改成一个AndroidView。

//Flutterclass _MyHomePageState extends State<MyHomePage> {  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),      ),    );  }}

在Android端也要加上对应的代码,为了更好地看出裁切效果,这里使用ImageView。

//Android@Overridepublic PlatformView create(final Context context, int i, Object o) {    final ImageView imageView = new ImageView(context);    imageView.setLayoutParams(new ViewGroup.LayoutParams(500,500));    imageView.setBackground(context.getResources().getDrawable(R.drawable.idle_fish));    return new PlatformView() {        @Override        public View getView() {            return imageView;        }        @Override        public void dispose() {        }    };}

在Flutter中嵌入Native组件的解决方法是什么

首先先看AndroidView,AndroidView对应的RenderObject是RenderAndroidView,而一个RenderObject的最终大小的确定是存在两种可能,一种是由父节点所指定,还有一种是在父节点指定的范围中根据自身情况确定大小。打开对应的源码,可以看到其中有个很重要的属性sizedByParent = true,也就是说AndroidView的大小是由其父节点所决定的,我们可以使用Container、SizedBox等控件控制AndroidView的大小。

AndroidView的绘图数据是Native层所提供的,那么当Native中渲染的View的实际像素大小大于AndroidView的大小时,会发生什么呢?通常情况下,这种情况的处理思路无非就两种选择,一种是裁切,另一种是缩放。Flutter保持了其一贯的做法,所有out of the bounds的Widget统一使用裁切的方式进行展示,上面所描述的情况就被当作是一种out of the bounds。

当这个View的实际像素大小小于AndroidView的时候,会发现View并不会相应地变小(Container的背景色并没有显露出来),没有内容的地方会被白色填充。这其中的原因是SingleViewPresentation::onCreate中,会使用一个FrameLayout作为rootView。

2.3. 触摸事件如何传递

Android的事件流大家应该都很熟悉了,自顶向下传递,自底向上处理或回流。Flutter同样是使用这一规则,但是其中AndroidView通过两个类来去处理手势:

MotionEventsDispatcher:负责将事件封装成Native的事件并向Native传递;

AndroidViewGestureRecognizer:负责识别出相应的手势,其中有两个属性:

在Flutter中嵌入Native组件的解决方法是什么

cachedEventsforwardedPointers,只有当PointerEvent的pointer属性在forwardedPointers中时才会去进行分发,否则会存在cacheEvents中。这里的实现主要是为了解决一些事件的冲突,比如滑动事件,可以通过gestureRecognizers来进行处理,这里可以参考官方注释。

/// 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]./// /// GestureDetector(///   onVerticalDragStart: (DragStartDetails d) {},///   child: AndroidView(///     viewType: 'WEBview',///     gestureRecognizers: <OneSequenceGestureRecognizer>[],///   ),/// )/// /// 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: 100.0,///     child: AndroidView(///       viewType: 'webview',///       gestureRecognizers: <OneSequenceGestureRecognizer>[ new VerticalDragGestureRecognizer() ],///     ),///   ),/// )

“在Flutter中嵌入Native组件的解决方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 在Flutter中嵌入Native组件的解决方法是什么

本文链接: https://lsjlt.com/news/240024.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 在Flutter中嵌入Native组件的解决方法是什么
    本篇内容介绍了“在Flutter中嵌入Native组件的解决方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 使用教程1.1. ...
    99+
    2023-06-04
  • iOS项目嵌入Flutter运行的方法是什么
    今天小编给大家分享一下iOS项目嵌入Flutter运行的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一 ...
    99+
    2023-07-05
  • Java中的Native方法是什么
    这期内容当中小编将会给大家带来有关Java中的Native方法是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。以下是java中如何使用native方法的基本语法:[ public ...
    99+
    2023-06-22
  • JavaScript嵌入网页中的方法是什么
    这篇文章主要讲解了“JavaScript嵌入网页中的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript嵌入网页中的方法是什么”吧!...
    99+
    2024-04-02
  • Python中web嵌入GUI的方法是什么
    这篇文章主要讲解了“Python中web嵌入GUI的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中web嵌入GUI的方法是什么”吧!随着Web技术的蓬勃发展,以网页形...
    99+
    2023-06-01
  • unity嵌入winform的方法是什么
    在Unity中嵌入WinForms控件,可以使用Windows Forms Host控件。以下是实现的步骤:1. 在Unity中创建...
    99+
    2023-09-20
    unity winform
  • JavaScript在网页设计中的嵌入应用方法是什么
    本篇内容主要讲解“JavaScript在网页设计中的嵌入应用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript在网页设计中的嵌入应用方法是什么”吧!---- JavaS...
    99+
    2023-06-03
  • java元组嵌套的方法是什么
    在Java中,可以使用List或者Map来模拟元组嵌套的结构。具体的方法如下: 使用List: List<Object&g...
    99+
    2024-03-04
    java
  • React Native 中限制导入某些组件和模块的方法
    目录限制使用 Touchable限制使用 Image同时限制两者示例有些时候,我们不希望使用某些组件,而是想使用其他组件。这时候,我们可以使用一个名为 no-restric...
    99+
    2022-11-13
    React Native 限制导入 React Native 导入组件模块
  • python列表嵌套元组的方法是什么
    在Python中,可以使用列表嵌套元组的方法来创建一个包含多个元组的列表。列表嵌套元组可以通过以下几种方式创建: 直接在列表中定...
    99+
    2023-10-22
    python
  • Repeater中嵌套Repeater的方法是什么
    在 ASP.NET 中,可以使用嵌套的 Repeater 控件来实现一个 Repeater 控件中嵌套另一个 Repeater 控件...
    99+
    2023-08-15
    Repeater
  • React中嵌套组件的构建顺序是什么
    这篇文章将为大家详细讲解有关React中嵌套组件的构建顺序是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。这里有一个疑问是,在嵌套组件中,是父组件先构建,还是子组件先构建?是子组件先更新...
    99+
    2023-06-14
  • 控件Repeater嵌套使用的方法是什么
    在ASP.NET中,可以通过在Repeater控件的ItemTemplate中嵌套另一个Repeater控件来实现Repeater的...
    99+
    2023-09-25
    Repeater
  • Vue中对组件二开的方法是什么
    这篇文章主要介绍“Vue中对组件二开的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue中对组件二开的方法是什么”文章能帮助大家解决问题。一、背景在对antdv、element、自定义组...
    99+
    2023-07-06
  • vue在antDesign框架或elementUI框架组件native事件中触发问题怎么解决
    这篇文章主要介绍了vue在antDesign框架或elementUI框架组件native事件中触发问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue在antDesign框架或elementUI框架...
    99+
    2023-06-30
  • python中numpy数组的csv文件写入与读取方法是什么
    这篇文章主要讲解了“python中numpy数组的csv文件写入与读取方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“python中numpy数组的csv文件写入与读取方法是什么”吧...
    99+
    2023-07-05
  • Flutter事件监听与EventBus事件应用的方法是什么
    这篇文章主要介绍“Flutter事件监听与EventBus事件应用的方法是什么”,在日常操作中,相信很多人在Flutter事件监听与EventBus事件应用的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家...
    99+
    2023-07-06
  • Flutter视频滚动播放的解决方案是什么
    Flutter视频滚动播放的解决方案是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。视频列表滚动播放。分类视频列表的播放规则一般需要和具体产品、交互确认,播放一般都是静...
    99+
    2023-06-04
  • Vue中子组件访问父组件数据的方法是什么
    本篇内容主要讲解“Vue中子组件访问父组件数据的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue中子组件访问父组件数据的方法是什么”吧!props官方解释:所有的 prop 都使得...
    99+
    2023-06-27
  • SimpleFramework组件开发的方法是什么
    本篇内容介绍了“SimpleFramework组件开发的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Simple组件是基于Web...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作