Flutter原生SwiftUI集成插件native_swiftui_pastebutton_and_textfield的使用

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

Flutter 原生 SwiftUI 集成插件 native_swiftui_pastebutton_and_textfield 的使用

native_swiftui_pastebutton_and_textfield

这是一个插件,它提供了从原生 SwiftUI 中提取的粘贴按钮和文本框作为 Flutter 小部件。

此插件需要使用 Xcode 构建,并且必须使用 iOS 版本 16.0 或更高版本。

开始使用

添加依赖

pubspec.yaml 文件中添加以下依赖:

dependencies:
  native_swiftui_pastebutton_and_textfield: ^1.0.7
导入包

如果你想要使用 PasteButton,请导入以下包:

import 'package:native_swiftui_pastebutton_and_textfield/NativePasteButtonWidget.dart';

如果你想要使用 TextField,请导入以下包:

import 'package:native_swiftui_pastebutton_and_textfield/NativeTextFieldWidget.dart';

简单使用

Scaffold(
  body: SafeArea(
    child: Column(
      children: [
        NativeTextFieldWidget(
            labelText: "写入提示",
            onUpdated: (String? text) {
              print(text);
            }),
        NativePasteButtonWidget(
            width: 90, // 默认宽度
            height: 50, // 默认高度
            color: Colors.redAccent,
            hasLabel: true,
            onPressed: (String? data) {
              print(data);
            })
      ],
    ),
  ),
);

使用此插件的原因

从 iOS 16 开始,当你尝试通过编程执行粘贴操作时,会弹出一个请求用户确认的提示。这个提示始终会在粘贴操作中出现,除非你使用原生 iOS 文本字段的编辑选项菜单、实现 UIPasteControl 的控件或键盘快捷键进行粘贴。

这会对用户体验造成显著影响。想象一下,如果你发布了一个记事本应用,每次粘贴时都会弹出提示;因为消费者没有耐心去关闭设置中的通知,该应用可能会得到一星评价。 😰

在原生 iOS 应用中,上述三种方法允许无提示粘贴。然而,在 Flutter 应用中,即使你通过 CupertinoTextField 的编辑选项菜单或使用键盘快捷键粘贴,它也不会被视为原生粘贴。实际上,它是通过编程执行的,因此会触发用户权限提示。自然地,创建一个粘贴按钮并不允许实现 UIPasteControl,导致提示的出现。

KakaoTalk_Video_2023-09-18-11-00-47

这个问题不仅限于 Flutter 框架。无论使用哪种框架,如果你通过普通按钮或手势检测器创建粘贴按钮,提示仍然会出现。

这促使我相信有必要创建一个原生 iOS 视图,从而催生了此插件。官方 Flutter 页面最初建议使用平台视图来利用 UIKit 组件提供原生 iOS 视图,这似乎允许实现 UIPasteControl。虽然在调试阶段这种方法运行得相当顺利,但在发布阶段却出现了令人讨厌的提示。因此,我决定利用 SwiftUI 的 PasteButton 并采用集成 SwiftUI 视图的方法。这种方法非常有效,我已使用它发布了 App Store 应用。

KakaoTalk_Video_2023-09-18-11-00-53

也许将来 Flutter 可能会支持 UIPasteControl。但目前,这个插件非常有用。

请确保检查

在 Xcode 中,你必须将 iOS 构建版本设置为 16.0 或更高版本。 首次启动时,iOS 目标版本有时会恢复到之前的设置,请务必再次检查。 不确定是否可以在插件中指定最小部署版本。

只需检查以下三项:

  1. 截图
  2. 截图
  3. 截图

示例代码

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '原生测试',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlueAccent),
        useMaterial3: false,
      ),
      home: const MainPage(),
    );
  }
}

更多关于Flutter原生SwiftUI集成插件native_swiftui_pastebutton_and_textfield的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生SwiftUI集成插件native_swiftui_pastebutton_and_textfield的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用native_swiftui_pastebutton_and_textfield插件的详细代码示例。这个插件假设已经通过SwiftUI创建了一个自定义的原生按钮和文本框,并希望将其集成到Flutter应用中。

1. 添加插件依赖

首先,在你的Flutter项目的pubspec.yaml文件中添加native_swiftui_pastebutton_and_textfield插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  native_swiftui_pastebutton_and_textfield:
    git:
      url: https://github.com/your-plugin-repo-url.git  # 替换为实际的插件仓库URL
      ref: main  # 或者特定的版本号

确保你已经替换了your-plugin-repo-url为实际的插件仓库URL。

2. 配置iOS平台

由于这个插件涉及到SwiftUI,你需要在iOS平台上进行一些配置。

2.1. 打开ios/Runner目录中的Podfile文件,并确保有以下内容:

platform :ios, '10.0'

target 'Runner' do
  use_frameworks!
  config = use_native_modules!

  # Flutter Pod
  flutter_install_all_ios_pods(File.dirname(File.realpath(__FILE__)))

  # Keep pod spec path relative so precompilation checks can pass.
  pod 'native_swiftui_pastebutton_and_textfield', :path => '../.symlinks/plugins/native_swiftui_pastebutton_and_textfield/ios'
end

2.2. 创建插件的桥接头文件

ios/Runner目录下,创建一个名为NativeSwiftUIPasteButtonAndTextFieldBridge.swift的文件,并添加以下内容:

import Flutter
import UIKit
import SwiftUI

@objc class NativeSwiftUIPasteButtonAndTextFieldBridge: NSObject, FlutterPlatformViewFactory {
    static let factory = NativeSwiftUIPasteButtonAndTextFieldBridge()

    func createWithFrame(frame: CGRect, viewIdentifier viewId: Int64, arguments launchArgs: Any?, binaryMessenger messenger: FlutterBinaryMessenger) -> FlutterPlatformView {
        let controller = UIHostingController(rootView: createSwiftUIView())
        return FlutterPlatformView(rootViewController: controller, viewIdentifier: viewId)
    }

    private func createSwiftUIView() -> some View {
        return ContentView()
    }
}

// SwiftUI View
struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
            TextField("Enter text...", text: $text)
                .padding()
                .border(Color.gray)

            Button(action: {
                if let pasteboard = UIPasteboard.general, let pasteString = pasteboard.string {
                    text = pasteString
                }
            }) {
                Text("Paste")
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
        .padding()
    }
}

3. 在Flutter中使用插件

在你的Flutter代码中,你可以通过MethodChannel与原生代码进行交互,但由于我们在这里直接使用了FlutterPlatformView,我们只需要在Flutter中嵌入这个视图即可。

3.1. 打开你的main.dart文件,并添加以下代码:

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

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

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

3.2. 在lib目录下创建一个新的Dart文件native_swiftui_pastebutton_and_textfield.dart,并添加以下内容:

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

class NativeSwiftUIPasteButtonAndTextFieldView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // This is where you would normally use a PlatformView,
    // but since we're using MethodChannel for communication in a real scenario,
    // we assume the native view is already set up and registered in the native code.
    // Here we simply return an empty container to represent where the native view would go.
    // In a real implementation, you would use a custom PlatformView.
    
    // Since we're directly embedding the native view, we won't need this empty container.
    // Instead, we will use UiKitView directly in Flutter 2.x and later.
    if (Platform.isIOS) {
      return UiKitView(
        viewType: 'com.example.native_swiftui_pastebutton_and_textfield/view',
        creationParams: null, // Any parameters you need to pass to the native view
        creationChannel: null, // If you have a separate channel for view creation
      );
    } else {
      // Fallback for non-iOS platforms
      return Container(
        child: Text('This feature is only available on iOS.'),
      );
    }
  }
}

4. 注册插件

最后,确保在你的AppDelegate.swift中注册插件:

import UIKit
import Flutter
import native_swiftui_pastebutton_and_textfield

@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)
  }
}

注意:上述代码假设native_swiftui_pastebutton_and_textfield插件已经正确实现了FlutterPlatformViewFactory。实际使用中,你需要确保插件的iOS实现部分正确无误,并且已经注册了相应的viewType

总结

以上代码演示了如何在Flutter项目中集成一个使用SwiftUI的原生视图。由于Flutter和原生代码的交互可能因插件的实现方式而异,请确保阅读插件的文档和示例代码,以便更好地理解其工作原理。

回到顶部