Using Platform Views
1. Understanding Platform Views Concept
Note: Platform Views in Flutter allow you to embed native platform views (such as Android Views or iOS UIViews) within a Flutter app, enabling access to native functionality while maintaining the Flutter UI.
| Feature | Description | Usage |
|---|---|---|
| AndroidView | Embeds an Android View in a Flutter app. | AndroidView(viewType: 'com.example.myview'); |
| UiKitView | Embeds a UIKit view in a Flutter app (iOS). | UiKitView(viewType: 'com.example.myuiview'); |
| Platform Views | Enables interaction between Flutter and native platform views. | Used for performance-critical or platform-specific UI components. |
Example: Using AndroidView
import 'package:flutter/material.dart';
class MyAndroidView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Platform Views Example")),
body: Center(
child: AndroidView(
viewType: 'com.example.myview',
),
),
),
);
}
}
Example: Using UiKitView
import 'package:flutter/material.dart';
class MyUiKitView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Platform Views Example")),
body: Center(
child: UiKitView(
viewType: 'com.example.myuiview',
),
),
),
);
}
}
Key Points
- Platform Views provide a bridge between Flutter and native platform views.
- They are useful for integrating existing native UI components or performance-critical features.
- Platform Views require platform-specific setup in Android and iOS projects.
2. Embedding Android Views
Flutter allows embedding native Android views within a Flutter app using platform views. This is useful for integrating existing Android UI components or accessing native Android APIs.
| Property | Description | Values |
|---|---|---|
| platformViewCreationPolicy | Controls when the platform view is created. | PlatformViewCreationPolicy.offline, PlatformViewCreationPolicy.online |
| viewType | Unique identifier for the platform view. | String |
| layoutDirection | Layout direction of the view. | LayoutDirection.ltr, LayoutDirection.rtl |
Example: Embedding Android View
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Android View Example")),
body: PlatformViewLink(
viewType: "com.example.androidview",
surfaceFactory: (context, controller) {
return AndroidViewSurface(
controller: controller,
gestureRecognizers: const {},
layoutDirection: LayoutDirection.ltr,
);
},
),
),
);
}
}
Note: Ensure that the
viewType matches the one registered in your Android code.
Warning: Platform views can impact performance and should be used sparingly.
3. Embedding iOS Views
Flutter allows embedding native iOS views using platform views. This is useful for integrating existing iOS components or leveraging platform-specific features.
| Property | Description | Values |
|---|---|---|
| platformViewCreationPolicy | Controls how the platform view is created. | PlatformViewCreationPolicy.offline, PlatformViewCreationPolicy.online |
| viewType | Identifier for the native view type. | NSString |
| layoutDirection | Layout direction for the view. | LayoutDirection.ltr, LayoutDirection.rtl |
Example: Embedding an iOS View
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class iOSViewEmbedder extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PlatformViewLink(
viewType: 'io.flutter.embedding.android.FlutterImageView',
surfaceFactory: (context, controller) {
return AndroidViewSurface(
controller: controller,
gestureRecognizers: const {},
);
},
platformViewCreationPolicy: PlatformViewCreationPolicy.offline,
);
}
}
Note: Ensure that the
viewType matches the native view identifier registered in your iOS project.
Warning: Platform views may impact performance and should be used sparingly.
4. Using PlatformViewLink Widget
The PlatformViewLink widget in Flutter allows you to create a link between a platform view and a Flutter widget, enabling interaction between native platform views and Flutter's UI.
| Property | Description | Values |
|---|---|---|
| viewType | Specifies the type of platform view to create. | 'native-view' or custom string |
| link | Provides a link to the platform view. | PlatformViewLink instance |
| platformViewCreationParams | Parameters used to create the platform view. | PlatformViewCreationParams |
Example: Using PlatformViewLink
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class PlatformViewExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Platform View Example')),
body: Center(
child: PlatformViewLink(
viewType: 'native-view',
onCreatePlatformView: (params) {
return PlatformViewsService.initNativeView(
id: params.id,
viewType: 'native-view',
layoutDirection: TextDirection.ltr,
);
},
),
),
);
}
}
5. Using HtmlElementView for Web
Example: Embedding HTML in Flutter Web
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('HtmlElementView Example')),
body: HtmlElementView(viewType: 'my-html-view'),
),
);
}
}
| Property | Description | Values |
|---|---|---|
| viewType | Identifier for the HTML element view | 'my-html-view' |
| onPlatformViewCreated | Callback when the view is created | Function(int id) |
Note: HtmlElementView is only supported on web and requires the view to be registered with
registerViewFactory.
Warning: Ensure that the HTML element is properly registered before using it in
HtmlElementView.
6. Implementing Native View Controllers
Example: Implementing a Native View Controller in iOS
import UIKit
import Flutter
@objc public class NativeViewController: UIViewController {
private var flutterView: UIView?
override public func viewDidLoad() {
super.viewDidLoad()
setupFlutterView()
}
private func setupFlutterView() {
let flutterEngine = FlutterEngine(name: "my_engine")
flutterEngine.run()
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
flutterView = flutterViewController.view
flutterView?.frame = view.bounds
view.addSubview(flutterView!)
}
}
| Property | Description | Notes |
|---|---|---|
| platformView | Instance of the native view controller | Used to embed native UI components |
| engine | Flutter engine instance | Must be initialized before embedding |
Note: Ensure the Flutter engine is properly initialized before attempting to embed native views.
Warning: Native view controllers must be managed carefully to avoid memory leaks or UI conflicts.
7. Handling View Lifecycle
Example: Platform View Lifecycle Management
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class PlatformViewLifecycle extends StatefulWidget {
@override
_PlatformViewLifecycleState createState() => _PlatformViewLifecycleState();
}
class _PlatformViewLifecycleState extends State<PlatformViewLifecycle> {
static const String platformViewType = 'platform_view';
late PlatformViewController controller;
@override
void initState() {
super.initState();
controller = PlatformViewsService.initPlatformView(
id: 'platform_view_id',
viewType: platformViewType,
layoutDirection: TextDirection.ltr,
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return PlatformViewLink(
url: 'https://example.com',
platformViewCreationParams: const PlatformViewCreationParams(),
builder: (BuildContext context, PlatformViewController controller) {
return Container(
width: 300,
height: 200,
child: AndroidView(
controller: controller,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>(() => EagerGestureRecognizer()),
},
),
);
},
);
}
}
| Method | Description | Notes |
|---|---|---|
| initPlatformView | Initializes a platform view with given parameters. | Must be called before using the view. Returns a PlatformViewController. |
| dispose | Releases resources associated with the view. | Should be called in dispose to prevent memory leaks. |
| setViewSize | Updates the size of the platform view. | Useful for dynamic resizing during runtime. |
Note: Platform views are managed by the Flutter engine and must be explicitly disposed to avoid memory leaks.
8. Managing Performance with Platform Views
Performance Considerations
- Platform views can cause jank if not managed carefully
- Use
AndroidViewandUiKitViewjudiciously - Minimize the number of platform views in a single screen
| Aspect | Impact | Best Practice |
|---|---|---|
| Rendering | Platform views are rendered outside the Flutter rendering tree | Use HardwareLayer for better performance |
| Memory Usage | Each platform view consumes additional memory | Reuse views where possible |
| Frame Rate | Can drop frame rate if too many views are active | Limit concurrent platform views to 2-3 |
Example: Using HardwareLayer
import 'package:flutter/material.dart';
class PerformanceExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: AndroidView(
androidFlingGestureEnabled: true,
hardwareAccelerated: true,
onPlatformViewCreated: (int id) {
// Handle view creation
},
),
),
);
}
}
Note: Enabling hardware acceleration can significantly improve rendering performance for complex platform views.
Warning: Avoid nesting multiple platform views inside each other as it can lead to severe performance degradation.
Optimization Workflow
- Profile the app using Flutter DevTools
- Identify platform view usage patterns
- Implement
hardwareAcceleratedproperty - Limit concurrent platform views
- Monitor frame rate post-optimization
9. Using webview_flutter Package
Example: Basic WebView Usage
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewExample extends StatefulWidget {
@override
_WebViewExampleState createState() => _WebViewExampleState();
}
class _WebViewExampleState extends State<WebViewExample> {
late WebViewController controller;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("WebView Example")),
body: WebView(
initialUrl: 'https://flutter.dev',
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);
}
}
| Property | Description | Values |
|---|---|---|
| initialUrl | URL to load initially | String |
| onWebViewCreated | Callback when WebView is created | Function(WebViewController) |
| javascriptMode | Enables JavaScript in WebView | JavaScriptMode.off, JavaScriptMode.unsafe |
Note: Ensure you add the required permissions in your app's manifest for Android and Info.plist for iOS.
10. Using google_maps_flutter Package
Example: Displaying a Google Map
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MapScreen(),
);
}
}
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
late GoogleMapController mapController;
final CameraPosition _cameraPosition = CameraPosition(
target: LatLng(37.42796133580664, -122.0857496559622),
zoom: 14.0,
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Google Map")),
body: GoogleMap(
initialCameraPosition: _cameraPosition,
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
),
);
}
}
| Property | Description | Values |
|---|---|---|
| initialCameraPosition | Initial position of the map camera | CameraPosition |
| onMapCreated | Callback when the map is created | void Function(GoogleMapController) |
| mapType | Style of the map | MapType.normal, MapType.satellite, MapType.terrain, MapType.hybrid |
| zoomControlsEnabled | Whether zoom controls are shown | true, false |
Note: Ensure you have added the necessary API keys in your app's configuration files for Android and iOS.