At present, the "Xianyu" client has been written in pure Flutter on the product detail page. It is no problem to write pure Flutter on a single page. By the way, I would like to mention how to easily identify whether a page is Flutter or native (not rigorous, when you know it In the case of Flutter, because RN will also be like this):
- Turn on the "Developer Mode" of the phone
- Turn on "Show layout boundaries"
- Switch back to APP
Take the product list page and product detail page of "Xianyu" as an example:
Product list page and product detail page
Next, we open the layout border display, you can see that Xianyu’s product list page (left) is natively written, so you can see the layout layer. The darker the color, the more layout layers, while the product details page (right) is Written by Flutter, there is only one layer of layout:
Ok, after the digression, let's start mixing Flutter in Android, using the previous "Daily" example.
The plan is like this:
- Transfer the outer UI framework, including toolbar, to the native for processing
- Flutter handles ListView, daily report data request logic, etc.
This can basically be a sub-simple mixed compilation example.
the simplest. . . Also count the official Flutter example (raw meat warning): https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps
New Flutter Module
If you want to mix Flutter in Native code, you need to create a Module in Flutter, which is officially created through the command line, but Android Studio's Flutter plugin also provides this function and is more intuitive, so here is Android Studio as an example:
Next project path, name, etc.:
Flutter Module path configuration
Then set the package name and click Finish again.
New Android project
Create a new Android project in the same parent directory of the Flutter Module, if the existing project is fine, the same is true.
Then go all the way next.
Introduce Flutter in Android project
Add the following code to the settings.gradle of the created Android project:
1 2 3 4 5 |
setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir.parentFile, 'flutter_daily_module/.android/include_flutter.groovy' )) |
Which settingsDir.parentFile
represents the parent directory of the current directory, which flutter_daily_module
is the Flutter Module directory created earlier.
You can see one Flutter
more library module by clicking Sync
Then rely on the library just introduced in the Build.gradle of the Application Module:
1 |
implementation project(':flutter') |
Android native code calls Flutter
Let's start with a simple Demo.
We changed the code in Flutter to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import 'dart:ui'; import 'package:flutter/material.dart'; void main() => runApp(_widgetForRoute(window.defaultRouteName)); Widget _widgetForRoute(String route) { switch (route) { case 'route1': return Center( child: Text('route: $route', textDirection: TextDirection.ltr), ); case 'route2': return Center( child: Text('route: $route', textDirection: TextDirection.ltr), ); default: return Center( child: Text('Unknown route: $route', textDirection: TextDirection.ltr), ); } } |
The above code will return a Widget, if the input parameter is, route1
it will be displayed in the center of the widget route: router1
.
In the MainActivity generated by the Android project by default, let's show a route1.
1 2 3 4 5 6 7 8 9 |
View flutterView = Flutter.createView( MainActivity.this, getLifecycle(), "route1" ); FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600, 800); layout.leftMargin = 100; layout.topMargin = 400; addContentView(flutterView, layout); |
Run the native Android project, you can see the following effects:
FlutterView is not the only way to use it. There is also a way of calling Flutter through FlutterFragment, as shown in the following code:
1 2 3 |
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.fl_flutter_view, Flutter.createFragment("route1")); fragmentTransaction.commit(); |
Which fl_flutter_view
corresponds to a FrameLayout defined in xml in Android:
1 2 3 4 |
<FrameLayout android:id="@+id/fl_flutter_view" android:layout_width="match_parent" android:layout_height="match_parent"/> |
The running effect chart is as follows:
FlutterFragment running effect
Flutter daily report list embedded in Android native outer framework
After completing the above steps, we have already understood how to call Flutter in Android. Below, we will embed the "Daily" list page of the actual combat series of articles in this "outer frame".
"Daily" pure Flutter project source code:
https://github.com/KevinWu1993/DailyFlutter
Let's first synchronize the main code of the list page in Flutter to flutter_daily_module.
The original "Daily" main.dart
code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import 'package:flutter/material.dart'; import 'package:zhihudaily/daily/daily_page.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: '日报', theme: ThemeData( primarySwatch: Colors.blue, ), home: DailyPage(title: '日报'), ); } } |
We changed main.dart in Flutter Module to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_daily_module/daily/daily_page.dart'; void main() => runApp(_widgetForRoute(window.defaultRouteName)); Widget _widgetForRoute(String route) { switch (route) { case 'dailyInNative': return MaterialApp( title: '日报', theme: ThemeData( primarySwatch: Colors.blue, ), home: DailyPage(title: '日报', isShowToolbar: false,), ); default: return MaterialApp( title: '日报', theme: ThemeData( primarySwatch: Colors.blue, ), home: DailyPage(title: '日报'), ); } } |
要注意的是default选项,因为Flutter Module也是可以独立运行的,所以留着这个case。
同样的在DailyPage
这一个Widget的构造方法里面,增加一个可选“是否显示Toolbar”的参数,目的是在独立运行flutter项目的时候显示状态栏,而在作为library module混编进Android的时候隐藏Toolbar,使用Android原生的Toolbar。
1 |
DailyPage({Key key, this.title, this.isShowToolbar = true}) : super(key: key); |
对于Flutter Toolbar,在DailyPage
中构建的方法如下:
1 2 3 4 5 6 7 8 |
Widget _buildAppBar(BuildContext buildContext) { if (widget.isShowToolbar) return new AppBar( title: Text(widget.title), ); else return null; } |
完成上述步骤后,在Android原生代码中调用如下:
1 2 3 |
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.fl_flutter_view, Flutter.createFragment("dailyInNative")); fragmentTransaction.commit(); |
Now that the embedding of the daily report list is completed, let's run it:
When running in Flutter standalone mode, it looks like this:
Flutter independent operation effect
There is no picture and no truth. Let’s end this article with a layout boundary comparison diagram. Pay attention to the Toolbar. One is native and the other is Flutter:
The authors: Kevin Wu
Article link: https://kevinwu.cn/p/964c6c3/