美文网首页
Flutter 与原生交互4

Flutter 与原生交互4

作者: Cat_uncle | 来源:发表于2022-03-22 22:56 被阅读0次

    对于混合开发的应用而言,通常我们只会将应用的部分模块修改成 Flutter 开发,其他模块继续保留原生开发,因此应用内除了 Flutter 的页面之外,还会有原生 Android、iOS 的页面。在这种情况下,Flutter 页面有可能会需要跳转到原生页面,而原生页面也可能会需要跳转到 Flutter 页面。这就涉及到了一个新的问题:如何统一管理原生页面和 Flutter 页面跳转交互的混合导航栈。

    示例 从原生跳转Flutter在跳回原生
    Flutter 代码

    import 'dart:ui';
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:flutter/foundation.dart';
    
    
    
    void main() => runApp(
    
       _widgetForRoute(window.defaultRouteName)
    
    );
    const platform = MethodChannel('samples.chenhang/navigation');
    
    
    Widget _widgetForRoute(String route) {
    
     switch (route) {
    
       default:
         return MaterialApp(
           theme: ThemeData(
               pageTransitionsTheme: PageTransitionsTheme(builders: {
                 TargetPlatform.android: CupertinoPageTransitionsBuilder(),
                 TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
           })),
           home:DefaultPage(showBack: true),
         );
     }
    }
    
    class PageA extends StatelessWidget {
    
     bool showBack;
     PageA({ Key key, this.showBack=false }) : super(key: key);
     @override
     Widget build(BuildContext context) {
       return Scaffold(
               backgroundColor: Colors.greenAccent,
               appBar: AppBar(title: Text("Flutter Page A")),
               body: Center(
                 child: Column(
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: <Widget>[
                     Text('Page A',
                       textDirection: TextDirection.ltr,
                       style: TextStyle(
                         fontSize: 20.0,
                         color: Colors.black,
                       ),
                     ),
                     RaisedButton(
                       child: Text("Go Native Page"),
                       onPressed: ()=>platform.invokeMethod('openNativePage')
                     )
                   ],
                 ),
               )
       );
     }
    }
    
    class DefaultPage extends StatelessWidget {
    
     bool showBack;
     DefaultPage({Key key, this.showBack=false }) : super(key: key);
    
     @override
     Widget build(BuildContext context) {
       return Scaffold(
           backgroundColor: Colors.redAccent,
           appBar: AppBar(
               title: Text("Flutter Default Page"),
               leading: !showBack?
               null:IconButton(
                   icon:Icon(Icons.arrow_back),
                   onPressed:() => platform.invokeMethod('closeFlutterPage')
               )),
           body: Center(
             child: Column(
               mainAxisAlignment: MainAxisAlignment.center,
    
               children: <Widget>[
                 Text(
                   'Default Page',
                   textDirection: TextDirection.ltr,
                   style: TextStyle(
                     fontSize: 20.0,
                     color: Colors.black,
                   ),
                 ),
                 RaisedButton(
                     child: Text("Go Page A"),
                     onPressed: ()=>Navigator.push(
                         context, MaterialPageRoute(
                         builder: (context) => PageA())),
                 )
    
               ],
             ),
           )
    
       );
     }
    }
    

    iOS端代码

    FlutterHomeViewController *vc = [[FlutterHomeViewController alloc]init];
    [vc setInitialRoute:@"defaultPage"];    
    [self.navigationController pushViewController:vc animated:YES];
    
    #import <UIKit/UIKit.h>
    #import <Flutter/Flutter.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface FlutterHomeViewController : FlutterViewController
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    #import "FlutterHomeViewController.h"
    #import "SomeOtherNativeViewController.h"
    
    @interface FlutterHomeViewController ()
    
    @end
    
    @implementation FlutterHomeViewController
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"samples.chenhang/navigation" binaryMessenger:self];
        
        [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
            // Note: this method is invoked on the UI thread.
            if([call.method isEqualToString:@"openNativePage"]) {
        
                SomeOtherNativeViewController *vc = [[SomeOtherNativeViewController alloc] init];
                [self.navigationController pushViewController:vc animated:YES];
                result(@0);
            }
            else if([call.method isEqualToString:@"closeFlutterPage"]) {
                [self.navigationController popViewControllerAnimated:YES];
                result(@0);
            }
            else {
                result(FlutterMethodNotImplemented);
            }
        }];
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [[self navigationController] setNavigationBarHidden:YES animated:animated];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        [[self navigationController] setNavigationBarHidden:NO animated:animated];
    
    }
    
    @end
    
    #import "SomeOtherNativeViewController.h"
    #import "FlutterHomeViewController.h"
    @interface SomeOtherNativeViewController ()
    
    @end
    
    @implementation SomeOtherNativeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor greenColor];
        self.title = @"Other Native Page";
        [self.view addSubview:({
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 30)];
            label.text = @"Some Native ViewController";
            label.textAlignment = NSTextAlignmentCenter;
            label;
        })];
        
        [self.view addSubview:({
            UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            
            button.frame = CGRectMake(50, 250, 120, 30);
            
            button.adjustsImageWhenHighlighted = NO;
            button.adjustsImageWhenDisabled = NO;
            button.showsTouchWhenHighlighted = YES;
            [button setTitle:@"Open Flutter" forState:UIControlStateNormal];
            [button addTarget:self action:@selector(openFlutterVC) forControlEvents:UIControlEventTouchUpInside];
            button;
            
        })];
        
        // Do any additional setup after loading the view.
    }
    
    
    - (void)openFlutterVC {
        FlutterHomeViewController *vc = [[FlutterHomeViewController alloc]init];
        [vc setInitialRoute:@"defaultPage"];
        [self.navigationController pushViewController:vc animated:YES];
    }
    
    @end
    

    Android 端代码

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn = findViewById(R.id.button);
            btn.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    Intent intent = new Intent(MainActivity.this, FlutterPageActivity.class);
                    startActivity(intent);
                }
            });
    
        }
    }
    
    public class FlutterPageActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getSupportActionBar().hide();
    
            FlutterView flutterView = Flutter.createView(this,getLifecycle(),"defaultRoute");
            //注册方法通道
            new MethodChannel(flutterView, "samples.chenhang/navigation").setMethodCallHandler(
                    new MethodChannel.MethodCallHandler() {
                        @Override
                        public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                            //如果方法名为打开新页面
                            if(call.method.equals("openNativePage")) {
                                //新建Intent,打开原生页面
                                Intent intent = new Intent(FlutterPageActivity.this, SomeNativePageActivity.class);
                                startActivity(intent);
                                result.success(0);
                            }
                            //如果方法名为关闭Flutter页面
                            else if(call.method.equals("closeFlutterPage")) {
                                //销毁自身(Flutter容器)
                                finish();
                                result.success(0);
                            }
                            else {
                                //方法未实现
                                result.notImplemented();
                            }
                        }
                    });
            setContentView(flutterView);
        }
    
    }
    
    
    public class SomeNativePageActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_some_native);
            android.support.v7.app.ActionBar actionBar = getSupportActionBar();
            if(actionBar != null){
                actionBar.setHomeButtonEnabled(true);
                actionBar.setDisplayHomeAsUpEnabled(true);
            }
    
            Button btn = findViewById(R.id.buttonx);
            btn.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    Intent intent = new Intent(SomeNativePageActivity.this, FlutterPageActivity.class);
                    startActivity(intent);
                }
            });
        }
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case android.R.id.home:
                    this.finish(); // back button
                    return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
    

    相关文章

      网友评论

          本文标题:Flutter 与原生交互4

          本文链接:https://www.haomeiwen.com/subject/gmjndrtx.html