How to display iOS native View in flutter?

Nonsense opening: Some people say that flutter is a major trend in the future, you must learn it, you must be able to use it! Some people say that native is the foundation, and flutter only replaces some of the functions of native UI. Some product managers think that flutter is omnipotent and dominates the mobile terminal. In fact, it sounds like a pity. This is not a qualified product manager, at least there is no in-depth research on how to polish the mobile terminal. It is a normal, maintainable and robust development strategy to choose the best from the best and eliminate the bad from the bad. A product manager without a vision is frustrating, and a product manager who doesn't listen is desperate.

In the face of flutter's inability to implement a functional interface but proficient in native development, how to build native UI for nesting?

Creating a FlutterCustomView class under iOS follows the FlutterPlatformViewFactory proxy protocol

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

@interface FlutterCustomView : NSObject <FlutterPlatformViewFactory>

@end
复制代码

Need to implement the constructor in the proxy method

这里可以获得需要展示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];

}
复制代码

Creating a FlutterCustomViewObject class under iOS follows the FlutterPlatformView protocol

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

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

@end
复制代码

Need to implement the constructor in the proxy method


- (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;

    });
}
复制代码

The player here uses the JPVideoPlayer third party, which is very easy to use.

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

How to register native UI components to flutter?

First, add the io.flutter.embedded_views_preview : true key-value pair to the info.plist file in the xcode project, which means that flutter can embed native UI components.

image.png

Then, register the currently packaged component in the appDelete file.


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

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

How to use this registered native UI component in flutter?

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(),
        )
      ],
    ),
  );
}
复制代码

Due to the refresh mechanism of flutter, if you want to ensure that the video playback will not restart due to switching the interface, you need to inherit the widget component from StatefulWidget, and set the corresponding State as follows:

image.png

image.png

Full code:

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;
}
复制代码

The final look:

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

Personal summary, some things are very helpful for development, so here is a record, masters do not spray, everyone's functional progress. [clasping fists] [clasping fists] [clasping fists]

Guess you like

Origin juejin.im/post/6989416734117593119