Flutter 插件开发实践(一)

Flutter 插件开发记录

工具

  • Flutter 1.9.1

  • AndroidStudio 3.5.3

  • XCode 11.2.1

新建一个 名为 flutter_plugin_demo 的 Flutter 工程,以下称为主工程。

Android 部分插件开发

右键工程名,新建一个名为 flutter_plugin 的 Moudle ,所选模块为 Flutter Plugin,其间你可以根据选择依赖插件所支持的 Kotlin 或者是 Swift 语言。

Flutter 插件开发实践(一)_第1张图片

创建完 Plugin 之后,flutter_plugin 会自动创建一个 example 的 Flutter 项目,因为 example 下面 test 包下面的 MyApp 类名会和主工程的类名冲突,所以替换以下即可。

运行 example 工程

右键 example/lib/main.dart,Run main.dart。如果在 IOS 模拟器中 build 成功但是包如下错误:

The application's Info.plist does not contain CFBundleVersion.

则在 example/pubspec.yaml 中添加

version: 1.0.0+1

再次运行即可。

Flutter 插件开发实践(一)_第2张图片

这说明其实插件本身已经帮我们实现了获取运行平台的功能,下面以简单的实现 toast 功能。

用 AndroidStudio File/Open, 打开 flutter_plugin 工程:

Flutter 插件开发实践(一)_第3张图片

除此之外,还可以选中 android 文件夹,右键点击,找到 Flutter,Open Android module in Android Studio,如下图,因为有时候我用这种方式打开之后编写代码没有 API 提示,就各种尝试,看个人了,迷之正确。

Flutter 插件开发实践(一)_第4张图片

编辑 FlutterPlugin.java

package com.hcl.flutter_plugin;

import android.util.Log;
import android.widget.Toast;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** FlutterPlugin */
public class FlutterPlugin implements MethodCallHandler {

  private static final String TAG = FlutterPlugin.class.getSimpleName();


  private final Registrar registrar;

  //构造
  private FlutterPlugin(Registrar registrar) {
    this.registrar = registrar;
  }


  /**
   * Plugin registration.
   */
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_plugin");
    channel.setMethodCallHandler(new FlutterPlugin(registrar));
  }


  //来自Flutter的方法调用
  @Override
  public void onMethodCall(MethodCall call, Result result) {

    String target = call.method;
    switch (target) {
      case "getPlatformVersion":
        result.success("Android " + android.os.Build.VERSION.RELEASE);
        break;
      case "toast":
        String content = (String) call.arguments;
        Log.d(TAG, "toast: " + content);
        showToast(content);
        break;
      default:
        result.notImplemented();
        break;
    }

  }


  /**
   * 显示Toast
   *
   * @param content
   */
  private void showToast(String content) {
    Toast.makeText(registrar.context(), content, Toast.LENGTH_SHORT).show();
  }


}

编辑 flutter_plugin.dart

  • flutter_plugin/lib
import 'dart:async';

import 'package:flutter/services.dart';

class FlutterPlugin {

  //除了 MethodChannel 还有其他交互方式
  static const MethodChannel _channel =
      const MethodChannel('flutter_plugin');

  static Future get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  /**
   * 显示Toast
   */
  static Future showToast(String content)async {
    await _channel.invokeMethod("toast",content);
  }
}

调用运行

 FlutterAndroidPlugin.showToast("Hello World");

这里只实现了 Android 部分的代码,所以只能运行到 Android 模拟器。

Flutter 插件开发实践(一)_第5张图片

IOS 端的实现

用 XCode 打开 Xcode 打开 example 工程中 iOS 项目,找到 ios 目录下的 Runner.xcworkspace。找到 FlutterPlugin.m 文件,目录结构如下:

修改 handleMethodCall 方法

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSString* methodName=call.method;
    NSString * params = call.arguments;
  if ([@"getPlatformVersion" isEqualToString:methodName]) {
    result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
  } else if([@"toast" isEqualToString:methodName ]){

      [self showMessage:params duration:2];

  }else{

      result(FlutterMethodNotImplemented);
  }
}

再添加方法:

//Toast
-(void)showMessage:(NSString *)message duration:(NSTimeInterval)time
{
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;

    UIWindow * window = [UIApplication sharedApplication].keyWindow;
    UIView *showview =  [[UIView alloc]init];
    showview.backgroundColor = [UIColor grayColor];
    showview.frame = CGRectMake(1, 1, 1, 1);
    showview.alpha = 1.0f;
    showview.layer.cornerRadius = 5.0f;
    showview.layer.masksToBounds = YES;
    [window addSubview:showview];

    UILabel *label = [[UILabel alloc]init];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

    NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:15.f],
                                 NSParagraphStyleAttributeName:paragraphStyle.copy};

    CGSize labelSize = [message boundingRectWithSize:CGSizeMake(207, 999)
                                             options:NSStringDrawingUsesLineFragmentOrigin
                                          attributes:attributes context:nil].size;
    label.frame = CGRectMake(10, 5, labelSize.width +20, labelSize.height);
    label.text = message;
    label.textColor = [UIColor whiteColor];
    label.textAlignment = 1;
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont boldSystemFontOfSize:15];
    [showview addSubview:label];

    showview.frame = CGRectMake((screenSize.width - labelSize.width - 20)/2,
                                screenSize.height - 100,
                                labelSize.width+40,
                                labelSize.height+10);
    [UIView animateWithDuration:time animations:^{
        showview.alpha = 0;
    } completion:^(BOOL finished) {
        [showview removeFromSuperview];
    }];
}

即可。运行测试:

Flutter 插件开发实践(一)_第6张图片

Flutter Plugin 的引用

这里只说本地引用,之前测试的都是在插件的 example/main.dart 中进行的,现在如果要让要主工程也引用该插件,则只需在主工程的 pubspec.yaml 中添加依赖:

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_plugin:
    path: flutter_plugin  #这个路径根据你插件的路径填写
import 'package:flutter/material.dart';
import 'package:flutter_plugin/flutter_plugin.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Main"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            FlutterPlugin.showToast("Say Hello");
          },
          child: Text("Say Hello"),
        ),
      ),
    );
  }
}

效果图
Flutter 插件开发实践(一)_第7张图片
Flutter 插件开发实践(一)_第8张图片

最后

源码地址
贴一张自己学习Flutter的公众号,感兴趣的小伙伴可以一起学习哦。。。

Flutter 插件开发实践(一)_第9张图片

你可能感兴趣的:(Flutter 插件开发实践(一))