Flutter原生视图嵌入插件flutter_native_view的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter原生视图嵌入插件 flutter_native_view 的使用

flutter_native_view 是一个用于在Flutter应用中嵌入Windows原生窗口(如VLC媒体播放器或WebView)的插件。它通过直接操作Win32 API来实现高效性能,无需纹理、中间缓冲区或像素缓冲区的复制。

插件特性

  • 支持在Flutter中放置其他Widget在NativeView之上。
  • 多个NativeView实例支持。
  • 窗口移动处理和NativeView的位置调整。
  • 窗口大小调整处理和NativeView的尺寸调整。
  • Windows 10及以上版本的支持。
  • 正确地释放HWND和实例。
  • NativeView上放置半透明的Widget。
  • NativeView放入可滚动组件如ListView中。

设置步骤

1. 添加依赖

首先,在你的pubspec.yaml文件中添加flutter_native_view依赖:

dependencies:
  flutter_native_view: ^latest_version

然后运行flutter pub get来安装依赖。

2. 修改main.cpp

根据插件文档,在windows/runner/main.cpp中添加以下代码:

#include "flutter_native_view/flutter_native_view_plugin.h"

// 在创建Flutter窗口之后调用:
flutternativeview::NativeViewContainer::GetInstance()->Create();

3. 初始化插件并创建控制器

接下来,在Dart代码中初始化插件,并创建一个或多个NativeViewController实例。这里以嵌入VLC播放器为例:

import 'package:flutter/material.dart';
import 'package:flutter_native_view/flutter_native_view.dart';
import 'package:win32/win32.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterNativeView.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Native View Example')),
        body: Center(
          child: NativeViewExample(),
        ),
      ),
    );
  }
}

class NativeViewExample extends StatefulWidget {
  @override
  _NativeViewExampleState createState() => _NativeViewExampleState();
}

class _NativeViewExampleState extends State<NativeViewExample> {
  final controller = NativeViewController(
    handle: FindWindow(nullptr, 'VLC Media Player'.toNativeUtf16()),
    hitTestBehavior: HitTestBehavior.translucent,
  );

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return NativeView(
      controller: controller,
      width: 640.0,
      height: 480.0,
    );
  }
}

这个示例展示了如何初始化插件,创建一个NativeViewController,并将其实例化为NativeView,从而将VLC播放器嵌入到Flutter应用中。

结论

flutter_native_view 提供了一个强大的解决方案,使得开发者能够将Windows原生控件无缝集成到Flutter应用中。虽然目前仅支持Windows平台,但其高性能和灵活性使其成为处理复杂UI需求的理想选择。未来计划包括Linux支持以及更多功能的开发。如果你对此项目感兴趣,可以通过GitHub赞助或捐赠来支持作者继续开发。


更多关于Flutter原生视图嵌入插件flutter_native_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生视图嵌入插件flutter_native_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,flutter_native_view 插件允许你将原生视图(如Android的View或iOS的UIView)嵌入到Flutter界面中。这对于需要在Flutter应用中集成特定平台功能的场景特别有用。以下是一个基本的代码案例,展示如何在Flutter中使用flutter_native_view插件嵌入原生视图。

前提条件

  1. 确保你的Flutter开发环境已经配置好。
  2. 在你的pubspec.yaml文件中添加flutter_native_view依赖:
dependencies:
  flutter:
    sdk: flutter
  flutter_native_view: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get

Android端实现

1. 创建一个自定义的Android View

首先,在Android项目中创建一个自定义的View。例如,在android/app/src/main/java/com/example/yourapp/NativeView.java中:

package com.example.yourapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class NativeView extends View {
    private Paint paint;

    public NativeView(Context context) {
        super(context);
        init();
    }

    public NativeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public NativeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setTextSize(50);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("Hello from Native View!", 50, 100, paint);
    }
}

2. 在Flutter中注册并使用这个View

lib/main.dart中:

import 'package:flutter/material.dart';
import 'package:flutter_native_view/flutter_native_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Native View Example'),
        ),
        body: Center(
          child: NativeView(
            androidViewClass: 'com/example/yourapp/NativeView', // 注意这里的路径格式
            creationParams: <String, dynamic>{}, // 如果需要传递参数给原生View,可以在这里添加
            width: 300,
            height: 200,
          ),
        ),
      ),
    );
  }
}

iOS端实现

1. 创建一个自定义的UIView

在iOS项目中创建一个自定义的UIView。例如,在ios/Runner/NativeView.swift中:

import UIKit

class NativeView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setup()
    }

    private func setup() {
        backgroundColor = .red
    }

    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        context.saveGState()
        context.setFillColor(UIColor.white.cgColor)
        let text = "Hello from Native View!"
        let textBounds = text.boundingRect(with: CGSize(width: rect.width, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: 50)], context: nil)
        context.fill(CGRect(x: (rect.width - textBounds.width) / 2, y: (rect.height - textBounds.height) / 2, width: textBounds.width, height: textBounds.height))
        text.draw(in: CGRect(x: (rect.width - textBounds.width) / 2, y: (rect.height - textBounds.height) / 2, width: textBounds.width, height: textBounds.height), withAttributes: [.font: UIFont.systemFont(ofSize: 50)])
        context.restoreGState()
    }
}

2. 在Flutter中注册并使用这个View

同样在lib/main.dart中(注意,这里我们已经有了Flutter端的代码,但需要为iOS添加注册逻辑):

你需要在ios/Runner/Info.plist中添加对flutter_native_view的依赖声明(这一步通常插件安装时自动完成,但确保检查):

<key>io.flutter.embedded_views_preview</key>
<true/>

然后,在iOS的AppDelegate中(如果需要的话,这通常不是必需的,除非你有特殊的初始化逻辑):

import UIKit
import Flutter
import flutter_native_view

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

由于flutter_native_view插件在iOS上通常会自动处理UIView的注册,你通常不需要在Dart代码中显式指定iOS的View类名(除非有特殊需求)。上面的Dart代码已经足够在iOS上嵌入一个空白的原生视图(你需要自己绘制内容,如上面的Swift代码所示)。

总结

以上代码展示了如何在Flutter中使用flutter_native_view插件嵌入原生视图。注意,实际项目中可能需要处理更多的细节,比如参数传递、事件监听等,这些都可以参考flutter_native_view的官方文档和示例进行扩展。

回到顶部