flutter 如何让一个onTap手势在多个级别之下影响一个顶级字符串变量?

ar7v8xwq  于 2022-12-24  发布在  Flutter
关注(0)|答案(2)|浏览(106)

我创建了一个有状态的Widget作为我的主页,它带有一个String变量textToDisplay。

import 'package:flutter/material.dart';

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

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

class _MainPageState extends State<MainPage> {
  String textToDisplay = 'Choose option';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Text(
              '$textToDisplay',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(
              height: 20,
            ),
            Choices(onTap: (){setState(() {
              textToDisplay =
            });},),
          ],
        ),
      ),
    );
  }
}

然后,我在另一个名为Choices()的dart文件中创建了一个无状态小部件。

class Choices extends StatelessWidget {
  Choices({required this.onTap});

  final VoidCallback? onTap;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 20,
        ),
        Buttons(text: 'Option A', onTap: onTap),
        SizedBox(
          height: 10,
        ),
        Buttons(text: 'Option B', onTap: onTap),
      ],
    );
  }
}

其中有2个无状态窗口小部件按钮,具有ontap手势。

class Buttons extends StatelessWidget {
  Buttons({required this.text, required this.onTap});

  final String text;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        color: Colors.green,
        width: 100,
        height: 40,
        child: Text(
          text,
        ),
      ),
    );
  }
}

我可以将onTap手势向上传递到树中,但我需要做的是,当按下按钮时,它会更新变量textToDisplay,以显示选项A或选项B,具体取决于按下的是哪个按钮。
我想我可以用一个无状态的小部件(Choices())来实现这一点,因为数据不会改变,它只是被读取
任何帮助都将不胜感激。

eqfvzcg8

eqfvzcg81#

更新顶级字符串的一种方法是使用ValueChanged创建您自己的Callback。
下面是一个完整的工作示例:

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MainPage(),
        ),
      ),
    );
  }
}

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

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

class _MainPageState extends State<MainPage> {
  String textToDisplay = 'Choose option';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Text(
              textToDisplay,
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(
              height: 20,
            ),
            Choices(
              onTap: (val) {
                setState(() {
                  textToDisplay = val;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class Choices extends StatelessWidget {
  Choices({required this.onTap});

  final ValueChanged? onTap;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 20,
        ),
        Buttons(
          text: 'Option A',
          onTap: onTap,
        ),
        SizedBox(
          height: 10,
        ),
        Buttons(text: 'Option B', onTap: onTap),
      ],
    );
  }
}

class Buttons extends StatelessWidget {
  Buttons({required this.text, required this.onTap});

  final String text;
  final ValueChanged? onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        if (onTap != null) {
          onTap!(text);
        }
      },
      child: Container(
        color: Colors.green,
        width: 100,
        height: 40,
        child: Text(
          text,
        ),
      ),
    );
  }
}
dced5bon

dced5bon2#

可以使用带参数的函数

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

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

class _MainPageState extends State<MainPage> {
  String textToDisplay = 'Choose option';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Text(
              textToDisplay,
              style: const TextStyle(fontSize: 20),
            ),
            const SizedBox(
              height: 20,
            ),
            Choices(
              onTap: (text) {
                _chageText(text);
              },
            ),
          ],
        ),
      ),
    );
  }

  void _chageText(String text) {
    setState(() {
      textToDisplay = text;
    });
  }
}

class Choices extends StatelessWidget {
  const Choices({super.key, required this.onTap});

  final Function(String text) onTap;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const SizedBox(
          height: 20,
        ),
        Buttons(text: 'Option A', onTap: () => onTap('Option A')),
        const SizedBox(
          height: 10,
        ),
        Buttons(text: 'Option B', onTap: () => onTap('Option B')),
      ],
    );
  }
}

class Buttons extends StatelessWidget {
  const Buttons({super.key, required this.text, required this.onTap});

  final String text;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        color: Colors.green,
        width: 100,
        height: 40,
        child: Text(
          text,
        ),
      ),
    );
  }
}

相关问题