如何在flutter里展示iOS原生View?

废话开篇:有人说flutter是未来的大趋势,必须要学,必须会用!有人说原生是根基,flutter也只是替代原生UI部分功能。对于某些产品经理认为flutter是万能的,是移动端的主宰的观点,其实个人听起来让人觉得挺遗憾的,这不是一个合格的产品经理,至少从如何打磨移动端上没有做深入调研。优中取优,劣中除劣,才是一个正常的、可维护的、健壮的开发策略。一个没有远见的产品经理是让人沮丧的,一个听不进去意见的产品经理是让人绝望的。

面对flutter无法实现功能界面但又精通原生开发的朋友来说如何搭建原生UI进行嵌套?

iOS 下创建 FlutterCustomView 类遵循 FlutterPlatformViewFactory 代理协议

引入Flutter 头文件
#import <Flutter/Flutter.h>

@interface FlutterCustomView : NSObject <FlutterPlatformViewFactory>

@end
复制代码

需要实现代理方法里面的构造方法

这里可以获得需要展示View的frame,viewId,相关参数
- (nonnull NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args {

    return [[FlutterCustomViewObject alloc] initWithFrame:frame viewId:viewId args:args];

}
复制代码

iOS 下创建 FlutterCustomViewObject 类遵循 FlutterPlatformView 协议

#import <Flutter/Flutter.h>
@interface FlutterCustomViewObject : NSObject<FlutterPlatformView>

- (id)initWithFrame:(CGRect)frame viewId:(int64_t)viewId args:(id)args;

@end
复制代码

需要实现代理方法里面的构造方法


- (id)initWithFrame:(CGRect)frame viewId:(int64_t)viewId args:(id)args
{
    if (self = [super init]) {
    //接受参数
    }
    return self;

}

- (nonnull UIView *)view {
    //这里初始化自定义view,一个简单的视频播放器
    UIView * view = [[UIView alloc] initWithFrame:_frame];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [view jp_playVideoWithURL:[NSURL URLWithString:@"video/dcba079700164a60b08aaa3ea9cc8efe.mp4"]];

        view.jp_muted = NO;

    });
}
复制代码

这里的播放器用的是 JPVideoPlayer 第三方,非常好用。

platform :ios, '9.0'
target 'Runner' do
pod 'JPVideoPlayer', '~> 3.1.1'
end
复制代码

如何注册原生UI组件到flutter?

首先,在xcode 工程里的info.plist文件里添加 io.flutter.embedded_views_preview : true 键值对,意思是允许flutter 可以嵌入原生UI组件。

image.png

然后,在appDelete文件里注册一下当前封装好的组件。


FlutterCustomView * flutterCustomView = [[FlutterCustomView alloc] init];

[[self registrarForPlugin:@"WSLCustomView"] registerViewFactory:flutterCustomView withId:@"WSLCustomView"];
复制代码

如何在flutter里面使用这个注册好的原生UI组件?

Widget build(BuildContext context) {
  return new Container(
    child: new Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        new Container(
          height: 200,
          //这里可以判断当前flutter项目的运行平台,根据需求去添加对应的安卓组件即可
          child: (defaultTargetPlatform == TargetPlatform.iOS) ?  UiKitView(viewType: 'WSLCustomView') : new Container(),
        )
      ],
    ),
  );
}
复制代码

由于flutter的刷新机制,想要保证视频的播放不会因为切换界面而重新开始,就需要将widget组件继承自 StatefulWidget ,将对应的State 设置如下:

image.png

image.png

完整代码:

class MineCustomView extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return new MineCustomViewState();
  }
}

class MineCustomViewState extends State<MineCustomView> with AutomaticKeepAliveClientMixin{
  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          new Container(
            height: 200,
            child: (defaultTargetPlatform == TargetPlatform.iOS) ?  UiKitView(viewType: 'WSLCustomView') : new Container(),
          )
        ],
      ),
    );
  }
  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}
复制代码

最后的样子:

Simulator Screen Shot - iPhone 11 - 2021-07-27 at 09.26.13.png

个人总结,有些东西对于开发是很有帮助的,所以这里记录一下,高手勿喷,大家功能进步。[抱拳][抱拳][抱拳]

猜你喜欢

转载自juejin.im/post/6989416734117593119