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

kx7yvsdv  于 2023-03-09  发布在  Flutter
关注(0)|答案(1)|浏览(131)

我正在尝试实现一个下拉按钮,让用户在应用的语言之间切换,相应的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(),以便每次下拉按钮更改时页面都重建?
我尝试过在下拉按钮小部件的onChanged属性的每个switch语句中放置setState(),但这也不能重建页面。

fnx2tebb

fnx2tebb1#

正如Peter Koltai提到的,应该使用setState方法让应用程序知道它必须重建,但不必直接使用build方法中的_value,当执行build方法时,它每次也执行这两个函数。
我假设,如果您向每个WebViewWidget添加不同的键,它将正常重建。
此外,您并不完全需要switch语句,可以删除它,因为它什么也不做:

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

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

相关问题