如何在每次更改下拉按钮时使用 setStage() 强制重建页面? (颤动)

问题描述 投票:0回答:1

我正在尝试实现一个下拉按钮,让用户在我的应用程序的语言之间切换,相应的 Webview 容器将更改以匹配所选语言。我试图通过创建一个 _renderWebviewBox1() 函数来实现这一点,该函数返回与当前所选语言匹配的 Webview 控制器。

String? _value = "English";

  _renderWebviewBox1() {
    if (_value == "English") {
      return WebViewWidget(controller: _controller);
    } else if (_value == "Mi'gmaq") {
      return WebViewWidget(controller: _controller1Mig);
    } else {
      print("No translation yet");
      return null;
    }
  }

这是我的完整代码:

import 'package:flutter/material.dart';
import 'package:flutter_webview_practice/routes.dart';

import 'package:webview_flutter/webview_flutter.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MainPage(),
      initialRoute: RouteManager.homePage,
      onGenerateRoute: RouteManager.generateRoute,
    );
  }
}

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  late final WebViewController _controller = WebViewController()
    ..setBackgroundColor(Colors.transparent)
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..loadFlutterAsset("assets/aligns/hunter-3-align1.html")
    ..setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {
          debugPrint('WebView is loading (progress : $progress%)');
        },
      ),
    );

  late final WebViewController _controller2 = WebViewController()
    ..setBackgroundColor(Colors.transparent)
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..loadFlutterAsset("assets/aligns/hunter-3-align2.html")
    ..setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {
          debugPrint('WebView is loading (progress : $progress%)');
        },
      ),
    );

  late final WebViewController _controller1Mig = WebViewController()
    ..setBackgroundColor(Colors.transparent)
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..loadFlutterAsset("assets/aligns/hunter-3-align1-mig.html")
    ..setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {
          debugPrint('WebView is loading (progress : $progress%)');
        },
      ),
    );

  late final WebViewController _controller2Mig = WebViewController()
    ..setBackgroundColor(Colors.transparent)
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..loadFlutterAsset("assets/aligns/hunter-3-align2-mig.html")
    ..setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {
          debugPrint('WebView is loading (progress : $progress%)');
        },
      ),
    );

  String? _value = "English";

  _renderWebviewBox1() {
    if (_value == "English") {
      return WebViewWidget(controller: _controller);
    } else if (_value == "Mi'gmaq") {
      return WebViewWidget(controller: _controller1Mig);
    } else {
      print("No translation yet");
      return null;
    }
  }

  _renderWebviewBox2() {
    if (_value == "English") {
      return WebViewWidget(controller: _controller2);
    } else if (_value == "Mi'gmaq") {
      return WebViewWidget(controller: _controller2Mig);
    } else {
      print("No translation yet");
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FittedBox(
          alignment: Alignment.center,
          fit: BoxFit.contain,
          child: Column(
            children: [
              DropdownButton<String>(
                value: _value,
                items: <String>[
                  "English",
                  "Mi'gmaq",
                  "Wolastoqey",
                ].map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (String? newValue) {
                  if (newValue != _value) {
                    switch (newValue) {
                      case "Mi'gmaq":
                        _value = "Mi'gmaq";
                        break;
                      case "English":
                        _value = "English";
                        break;
                      case "Wolastoqey":
                        _value = "Wolastoqey";
                        break;
                    }
                  }
                  setState(() {
                    _value = newValue;
                  });
                },
              ),
              Stack(
                children: [
                  Container(
                    width: 650,
                    height: 500,
                    child: const Image(
                      image: AssetImage("assets/images/hunterChoice3.jpg"),
                    ),
                  ),
                  Positioned(
                    left: 120,
                    right: 10,
                    top: 10,
                    bottom: 10,
                    child: Container(
                      width: 325,
                      height: 500,
                      child: _renderWebviewBox1(),
                    ),
                  ),
                  Positioned(
                    left: 20,
                    right: 90,
                    top: 420,
                    child: Container(
                      width: 325,
                      height: 500,
                      child: _renderWebviewBox2(),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

但是,目前,虽然下拉按钮会更新,但页面不会重建,因此 _renderWebviewBox1() 和 _renderWebviewBox2() 只被调用一次。我应该如何实现 setState() 以便每次更改下拉按钮时重新构建页面?

我尝试将 setState() 放在下拉按钮小部件中 onChanged 属性的每个 switch 语句中,但这也不会重建页面。

flutter dart webview setstate statefulwidget
1个回答
0
投票

正如Peter Koltai提到的,您应该使用

setState
方法让应用程序知道它必须重建,但没有必要直接在
_value
方法中使用
build
build
方法执行的时候,也是每次都执行这两个函数。

我假设如果您为每个

WebViewWidget
添加不同的密钥,它将正常重建。

此外,您完全不需要

switch
声明,它可以删除,因为它什么都不做:

onChanged: (String? newValue) {
  if (newValue != _value) {
    setState(() {
      _value = newValue;
    });
}

此外,当您到处使用复制粘贴代码时,请考虑创建函数或方法以减少代码重复。

© www.soinside.com 2019 - 2024. All rights reserved.