效果

本文具体demo效果如下

开发

1.首先创建flutter项目,在项目中定义好flutter需要展示布局:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Expanded(
            child: Center(
              child: Text(
                'Android按钮点击了 $_counter 次',
                style: const TextStyle(fontSize: 17.0)),
            ),
          ),
          Container(
            padding: const EdgeInsets.only(bottom: 15.0, left: 5.0),
            child: Row(
              children: <Widget>[
                Image.asset('assets/flutter-mark-square-64.png', scale: 1.5),
                const Text('Flutter', style: TextStyle(fontSize: 30.0)),
              ],
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _sendFlutterIncrement,
        child: const Icon(Icons.add),
      ),
    );
  }

上述代码所呈现的布局就是效果图中Flutter那一部分(上半部分),设置FloatingActionButton是为了呈现Flutter与Android的交互过程, "Android按钮点击了 $_counter 次"呈现的是交互结果,Image.asset()则显示的是Flutter的logo(标记这是flutter中的布局)。之所以这样做是因为Flutter与Android页面相互嵌套通产伴随着数据交互。

2.创建Android中的布局:

  <io.flutter.embedding.android.FlutterView
    android:id="@ id/flutter_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    />

  <androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:background="@color/grey"
    >

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      >

      <TextView
        android:id="@ id/button_tap"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/button_tap"
        ...
        />

      <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/android"
        ...
        />

    </LinearLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
      android:id="@ id/button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
       ...
      />

  </androidx.coordinatorlayout.widget.CoordinatorLayout>

io.flutter.embedding.android.FlutterView就是需要展示的flutter布局也就是第一步中编写的布局,剩下的部分和第一步的逻辑是一样的,有用来展示交互结果的TextView(@ id/button_tap),标记Android页面的TextView(@string/android),用来交互的按钮FloatingActionButton。

3.定义通信渠道

Flutter:

  static const String _channel = 'increment';
  static const String _pong = 'pong';
  static const String _emptyMessage = '';
  static const BasicMessageChannel<String> platform =
      BasicMessageChannel<String>(_channel, StringCodec());
  int _counter = 0;
  
  @override
  void initState() {
    super.initState();
    platform.setMessageHandler(_handlePlatformIncrement);
  }
  
 Future<String> _handlePlatformIncrement(String message) async {
    setState(() {
      _counter  ;
    });
    return _emptyMessage;
  }

  void _sendFlutterIncrement() {
    platform.send(_pong);
  }

代码中通信渠道使用的是BasicMessageChannel,没有用MethodChannel和EventChannel是因为BasicMessageChannel可以随时随地进行任何通信,而另外两种则各自有各自的局限性,这里就不做解释了,稍后会有文章专门介绍这三种通信渠道。_channel 是通信渠道的名称,这个是唯一且固定的,一旦定义好,Android端也要使用相同的名称,否则两者无法对接,导致通信失败。_pong是Flutter向Android传递的消息内容,Android每次接收的内容为"pong",相应的Flutter按钮点击次数就 1,消息内容和类型用户都可以自定义,只要定义好BasicMessageChannel的泛型和消息编码机制(文中使用的是StringCodec)即可。如果消息的内容比较多,开发者可以使用Json进行消息传递。_counter是flutter接收Android按钮的点击次数,Android按钮每点击一次_counter就 1。相关变量或常量定义完后,开发者需要在initState()中进行消息接收处理,因为BasicMessageChannel是双向通信,platform.setMessageHandler(_handlePlatformIncrement)就是对接收到的消息进行处理,_handlePlatformIncrement方法说明了消息的类型是String,消息是异步,_counter 1后调用setState()刷新布局后相应展示的Android按钮点击次数就 1了。platform.send(_pong)就是Flutter按钮点击完后调用这个方法,然后BasicMessageChannel将消息发送到Android。

Android:

    private static FlutterEngine flutterEngine;
    private FlutterView flutterView;
    private int counter;
    private static final String CHANNEL = "increment";
    private static final String EMPTY_MESSAGE = "";
    private static final String PING = "ping";
    private BasicMessageChannel<String> messageChannel;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            if (flutterEngine == null) {
            flutterEngine = new FlutterEngine(this, args);
            flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartEntrypoint.createDefault()
            );
        }
        ...
        flutterView = findViewById(R.id.flutter_view);
        flutterView.attachToFlutterEngine(flutterEngine);

        messageChannel = new BasicMessageChannel<>(flutterEngine.getDartExecutor(), CHANNEL, StringCodec.INSTANCE);
        messageChannel.
            setMessageHandler(new MessageHandler<String>() {
                @Override
                public void onMessage(String s, Reply<String> reply) {
                    onFlutterIncrement();
                    reply.reply(EMPTY_MESSAGE);
                }
            });

        FloatingActionButton fab = findViewById(R.id.button);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendAndroidIncrement();
            }
        });
        ...

CHANNEL 是通信渠道的名称也是渠道的标识符,一定要和flutter统一,否则无法通信。BasicMessageChannel是通信渠道,如果使用了和flutter端不一样的,也是无法通信的。EMPTY_MESSAGE是Android端收到Flutter消息后给Flutter的回复,表示让Flutter知道Android收到消息了。Android端收到消息后在setMessageHandler中进行消息处理:将flutter点击按钮次数 1( onFlutterIncrement()),同时回复确认收到的消息(reply.reply(EMPTY_MESSAGE))。FloatingActionButton发生点击事件后调用sendAndroidIncrement方法就会向Flutter发送消息说自己点击了一次按钮:

    private void sendAndroidIncrement() {
        messageChannel.send(PING);
    }

PING就是Android向Flutter发送的消息内容,Flutter收到消息后就对Android点击按钮次数 1。如果传递的消息比较多,还需要对具体的消息进行判断来确认需要做哪些处理,本文中只传递一种内容的消息,所以对消息的参数和方法没有做判断。代码中flutterView即是需要展示的Flutter布局,flutterEngine则是flutter引擎(说法不统一), flutterView.attachToFlutterEngine(flutterEngine)则是为flutterView注入生命和能量,否则flutterView就是空空没有生命和内容的控件。flutterEngine和AppCompatActivity的生命周期是绑定在一起:

  @Override
    protected void onResume() {
        super.onResume();
        flutterEngine.getLifecycleChannel().appIsResumed();
    }

    @Override
    protected void onPause() {
        super.onPause();
        flutterEngine.getLifecycleChannel().appIsInactive();
    }

    @Override
    protected void onStop() {
        super.onStop();
        flutterEngine.getLifecycleChannel().appIsPaused();
    }

    @Override
    protected void onDestroy() {
        flutterView.detachFromFlutterEngine();
        super.onDestroy();
    }

Android中一旦出现了对生命周期的绑定,就是说只要按要求来,就不会出现乱七八糟的问题,即使有问题也不是它的问题。

总结

  • Flutter与Android的交互在不断迭代中已经变得比较完善,最新Flutter版本中已经比Flutter早期的版中简单很多。
  • 如果能避免Flutter与Android的相互嵌套就尽量避免,因为两者的嵌套很耗能,可能出现卡顿、死机、高耗电等问题。

说明

有些代码展示不全,详情请查看demo。

以上就是如何在Flutter中嵌套Android布局的详细内容,更多关于Flutter中嵌套Android布局的资料请关注Devmax其它相关文章!

如何在Flutter中嵌套Android布局的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  9. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

  10. Flutter中文教程-Cookbook

    Flutter中文网的Cookbook中包含了在编写Flutter应用程序时常见问题及示例。设计基础使用主题共享颜色和字体样式Images显示来自网上的图片用占位符淡入图片使用缓存图Lists创建一个基本list创建一个水平list使用长列表创建不同类型子项的List创建一个gridList处理手势处理点击添加Material触摸水波效果实现滑动关闭导航导航到新页面并返回给新页面传值从新页面返回数据给上一个页面网络从网上获取数据进行认证请求使用WebSockets

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部