Flutter 插件開發實踐(一)

Flutter 插件開發記錄

工具

  • Flutter 1.9.1java

  • AndroidStudio 3.5.3android

  • XCode 11.2.1

新建一個 名爲 flutter_plugin_demo 的 Flutter 工程,如下稱爲主工程。ios

Android 部分插件開發

右鍵工程名,新建一個名爲 flutter_plugin 的 Moudle ,所選模塊爲 Flutter Plugin,其間你能夠根據選擇依賴插件所支持的 Kotlin 或者是 Swift 語言。git

建立完 Plugin 以後,flutter_plugin 會自動建立一個 example 的 Flutter 項目,由於 example 下面 test 包下面的 MyApp 類名會和主工程的類名衝突,因此替換如下便可。github

運行  example 工程

右鍵 example/lib/main.dart,Run main.dart。若是在 IOS 模擬器中 build 成功可是包以下錯誤:markdown

The application's Info.plist does not contain CFBundleVersion.
複製代碼

則在 example/pubspec.yaml 中添加app

version: 1.0.0+1
複製代碼

再次運行便可。less

這說明其實插件自己已經幫咱們實現了獲取運行平臺的功能,下面以簡單的實現 toast 功能。async

用 AndroidStudio File/Open, 打開 flutter_plugin 工程:ide

除此以外,還能夠選中 android 文件夾,右鍵點擊,找到 Flutter,Open Android module in Android Studio,以下圖,由於有時候我用這種方式打開以後編寫代碼沒有 API 提示,就各類嘗試,看我的了,迷之正確。

編輯 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<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

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

複製代碼

調用運行

FlutterAndroidPlugin.showToast("Hello World");
複製代碼

這裏只實現了 Android 部分的代碼,因此只能運行到 Android 模擬器。

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 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<MyHomePage> {
  @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"),
        ),
      ),
    );
  }
}

複製代碼
效果圖

最後

源碼地址

相關文章
相關標籤/搜索