Flutter视图控制器插件flutter_view_controller的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter视图控制器插件flutter_view_controller的使用

复杂界面无需费力即可实现。可重用组件具有完全控制其状态和布局的能力。父母与子之间双向通信变得容易。用户界面更新可以直接从您的业务逻辑中进行。所有这些功能以及更多功能,均采用优雅简洁的语法。

目录

层级

控制器由子控制器组成,子控制器作为参数传递给相应的子视图。

app.dart

class AppController extends Controller {
  ChildController child = ChildController();

  [@override](/user/override)
  onInit() {}

  [@override](/user/override)
  onClose() {}
}

class AppView extends ViewOf<AppController> {
  const AppView({required super.controller});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ChildView(controller: controller.child)
      )
    );
  }
}

child.dart

class ChildController extends Controller {
  [@override](/user/override)
  onInit() {}

  [@override](/user/override)
  onClose() {}
}

class ChildView extends ViewOf<ChildController> {
  const ChildView({required super.controller});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Text("Child");
  }
}

视图

视图部分负责构建布局。默认情况下,每个视图都是静态的。响应式通过通知器实现。

它可以用于整个页面或只是某个组件。每个视图都需要一个控制器,即使它不被使用。

view.dart

class ExampleView extends ViewOf<ExampleController> {
  const ExampleView({required super.controller});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      height: 30,
      width: 30,
      color: Colors.red,
      child: ...
    );
  }
}

控制器

Controller 类负责视图的行为。它包含视图的所有操作和属性,并且每个视图都有直接访问其对应控制器的方法。控制器包括方法和属性。

controller.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class ExampleController extends Controller {
  ButtonController _buttonController;
  int counter = 0;
  
  [@override](/user/override)
  onInit(){
    _configButtonController();
  }

  _configButtonController(){
    _buttonController.onClick.then(incrementCounter);
  }

  incrementCounter(){
    counter++;
  }

  [@override](/user/override)
  onClose(){}
}

通知器

通知器对于Flutter视图控制器组件的状态管理至关重要。它们负责通知视图关于属性的变化。如果您有会影响布局的数据,则需要使用通知器。

您需要在控制器中声明通知器,并且所有通知器都必须有一个类型。

视图更新

您可以使用 show 方法在其变化时进行监听。要改变通知器的值,只需将其设置为新值。

app.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class AppController extends Controller {

  Notifier<String> message = Notifier("Default Message");
  Notifier<int> number = Notifier(0);

  [@override](/user/override)
  onInit(){
    message.value = "New message";
    number.value++;
  }

  [@override](/user/override)
  onClose(){}
}

class AppView extends View<AppController> {
  AppView({required super.controller});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(children:[
      Container(
        child: controller.message.show((snapshotMessage) => Text(snapshotMessage))
      ),
      Container(
        child: controller.number.show((snapshotNumber) => Text(snapshotNumber.toString()))
      ),
    ]);
  }
}
监听控制器内的更改

您还可以在控制器内监听更改。

controller.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class MessageController extends Controller {
  Notifier<String> message = Notifier('Default Message');

  [@override](/user/override)
  onInit(){
    message.listen((snapshotMessage) =>  print(snapshotMessage));
  }

  [@override](/user/override)
  onClose(){}
}
连接通知器

您也可以连接到另一个通知器以传播更改。这在您有复杂的结构时非常有用。

child.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class ChildController extends Controller {

  Notifier<String> message = Notifier("Default Message");

  [@override](/user/override)
  onInit(){
    // 这将在父消息更新时生效
    message.listen((newMessage) => print(newMessage));
  }

  [@override](/user/override)
  onClose(){}
}

parent.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';
import 'child.dart';

class ParentController extends Controller {
  ChildController child = ChildController();
  Notifier<String> message = Notifier("Default Message");

  [@override](/user/override)
  onInit(){
    message.connect(child.message);
    message.value = "New message";
  }

  [@override](/user/override)
  onClose(){}
}
通知列表

您还可以使用 NotifierList 在布局中创建反应式列表。NotifierList 目前仍处于早期阶段,但它已经具备了改变其反应性的必要方法。

app.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class AppController extends Controller {

  NotifierList<String> messages = NotifierList();

  [@override](/user/override)
  onInit(){}

  addMessage(){
    messages.add('Message');
  }

  [@override](/user/override)
  onClose(){}
}

class AppView extends View<AppController> {
  AppView({required super.controller});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return controller.messages.show((messages) => 
      Column(
        children:[
          GestureDetector(
            onTap: controller.addMessage,
            child: Container(
                child: Text('Add message')
            ),
          ),
          ...messages.map((message) => Text(message))
          ]
        ),
    );
  }
}

注意,show 方法返回一个单个的 Widget,因为它始终返回一个 NotifierListener。因此,要在列表中使用它,您需要将整个列表包裹在其中。之后,您可以按需展开项目。

无值的通知器

如果您想在不改变任何值的情况下通知某些事件,可以使用 NotifierTicker。它可以通过所有通知器的功能生成脉冲。

然而,您不是向其添加新值,而是使用 tick() 方法触发它。此外,它的 show 方法不接受任何值。

app.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class AppController extends Controller {

  String message = 'Default Message';
  NotifierTicker ticker = NotifierTicker();

  [@override](/user/override)
  onInit(){}

  pulse(){
    message = 'New Message';
    ticker.tick();
  }

  [@override](/user/override)
  onClose(){}
}

class AppView extends View<AppController> {
  AppView({required AppController controller}) : super(controller: controller);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return controller.ticker.show(() => 
      GestureDetector(
        onTap: controller.pulse,
        child: Container(
            child: Text(controller.message)
        ),
      ),
    );
  }
}

NotifierTicker 用于内置的更新方法,该方法在所有受其控制的页面上刷新。

屏幕尺寸适配

为了简化小部件大小的计算,Flutter视图控制器在视图中带有一个内置属性。您可以随时访问屏幕宽度和高度,甚至可以根据视图计算百分比来调整组件的尺寸。

app.dart

import 'package:flutter_view_controller/flutter_view_controller.dart';

class AppView extends View<AppController> {
  AppView({required AppController controller}) : super(controller: controller);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      height: size.height(55.2),
      width: size.width(10),
      ...
    )
  }
}

更多关于Flutter视图控制器插件flutter_view_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视图控制器插件flutter_view_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用flutter_view_controller插件的示例代码。这个插件通常用于在原生iOS或Android应用中嵌入Flutter视图,并与之进行交互。

首先,确保你已经在pubspec.yaml文件中添加了flutter_view_controller依赖(尽管这个插件可能不直接存在,通常我们直接使用Flutter官方提供的嵌入机制,但这里为了说明概念,我们假设有这样一个插件)。不过,请注意,实际使用中,你可能需要使用的是Flutter Engine的嵌入API或其他相关插件。

dependencies:
  flutter:
    sdk: flutter
  flutter_view_controller: ^x.y.z  # 假设版本号存在,实际使用时替换为真实版本号

iOS端代码示例

在iOS项目中,你需要使用FlutterViewController来嵌入Flutter视图。以下是一个简单的示例,展示如何在iOS的ViewController中嵌入Flutter视图。

// ViewController.h
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>

@interface ViewController : UIViewController

@end
// ViewController.m
#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) FlutterViewController *flutterViewController;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化Flutter引擎
    FlutterEngine *flutterEngine = [[FlutterEngine alloc] initWithName:@"my_engine" project:nil];
    
    // 创建并配置FlutterViewController
    self.flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
    self.flutterViewController.modalPresentationStyle = UIModalPresentationFullScreen;
    
    // 将FlutterViewController作为当前视图控制器的子视图控制器
    [self presentViewController:self.flutterViewController animated:YES completion:nil];
}

@end

Android端代码示例

在Android项目中,你需要使用FlutterActivityFlutterFragment来嵌入Flutter视图。以下是一个使用FlutterActivity的简单示例。

首先,确保在AndroidManifest.xml中声明了FlutterActivity

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity
    android:name="io.flutter.embedding.android.FlutterActivity"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize" />

然后,在你的MainActivity中启动FlutterActivity

// MainActivity.java
package com.example.myapp;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import io.flutter.embedding.android.FlutterActivity;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 启动FlutterActivity
        startActivity(
            FlutterActivity
                .withCachedEngine("my_engine_id")
                .build(this)
        );
    }
}

注意,这里的withCachedEngine方法需要你先在应用中创建并缓存一个Flutter引擎。这通常在你的应用启动时完成:

// Application.java
package com.example.myapp;

import android.app.Application;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.android.FlutterActivity;

public class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // 创建并缓存Flutter引擎
        FlutterEngine flutterEngine = new FlutterEngine(this);
        FlutterEngineCache
            .getInstance()
            .put("my_engine_id", flutterEngine);
    }
}

Flutter端代码示例

在Flutter端,你可以像平常一样编写你的Dart代码。这部分代码将运行在嵌入的Flutter视图中。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter View Example'),
        ),
        body: Center(
          child: Text('Hello from Flutter!'),
        ),
      ),
    );
  }
}

请注意,上述代码是基于假设存在一个flutter_view_controller插件的情况编写的。实际上,Flutter的嵌入机制通常使用FlutterEngineFlutterActivity(Android)或FlutterViewController(iOS)来完成。希望这些示例代码能帮助你理解如何在原生应用中嵌入Flutter视图。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!