【问题标题】:Flutter : I want to change an image when you tap the image, and others are not affected by the tapFlutter : 我想在你点击图片的时候换一张图片,其他的不受点击的影响
【发布时间】:2021-10-21 14:08:19
【问题描述】:

我正在 Flutter 中创建一个简单的应用程序。 1 个屏幕上有 7 个图像。我需要一个功能,当您点击其中一个图像时,您可以更改图像。但是,现在当我点击一个图像时,其他 6 个图像也会改变。我将变量“isReal”放入 buildButton() 中,“isReal”将在 For 语句中切换真假,该语句在 buildButton() 中切换“isReal”。但是,那没有用。你能给我一些关于这个问题的建议吗?谢谢。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';

class Screen extends StatefulWidget {
  @override
  _ScreenState createState() => _ScreenState();
}

class _ScreenState extends State<Screen> {
  bool isReal = true;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            backgroundColor: Colors.teal[100],
            // appBar: AppBar(
            //     title: Text('AnimalSounds'), backgroundColor: Colors.teal),
            body: SafeArea(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  buildButton('cat.mp3', Colors.red, 'images/cat.png',
                      'images/cat_real.jpg'),
                  Expanded(
                      child: Row(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: <Widget>[
                        buildButton('dog.mp3', Colors.yellow, 'images/dog.png',
                            'images/cow.png'),
                        buildButton('cow.mp3', Colors.orange, 'images/cow.png',
                            'images/dog.png'),
                      ])),
                  Expanded(
                      child: Row(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: <Widget>[
                        buildButton('pig.mp3', Colors.green, 'images/pig.png',
                            'images/elephant.png'),
                        buildButton('elephant.mp3', Colors.teal,
                            'images/elephant.png', 'images/rooster.png'),
                        buildButton('rooster.mp3', Colors.blue,
                            'images/rooster.png', 'images/pig.png'),
                      ])),
                  Expanded(
                      child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: <Widget>[
                      buildButton('goat.mp3', Colors.purple, 'images/goat.jpg',
                          'images/pig.png'),
                    ],
                  )),
                ],
              ),
            )));
  }

  Expanded buildButton(sound, color, simpleImage, realImage) {
    return Expanded(
        child: FlatButton(
      onPressed: () {
        setState(() {
          isReal = !isReal;
        });
        final player = AudioCache();
        player.play(sound);
      },
      color: color,
      child: isReal ? Image.asset(simpleImage) : Image.asset(realImage),
    ));
  }
}

【问题讨论】:

    标签: flutter setstate


    【解决方案1】:

    好的,你有变量isReal 对整个类都是相同的(即每个按钮使用相同的变量)。因此,当您通过点击一个按钮更改它的值时,它也会影响所有其他按钮。

    为了解决这个问题,我建议将按钮实现移动到单独的Statefull 小部件中。这样您就可以将Screen 类保持为Stateless

    更新: 显然,您应该观看一些有关如何自己制作的教程。但就这一次来说,这就是你分离小部件后的样子。

    我在这里所做的是:

    1. 创建新的小部件类FlipButton
    2. 将代码从您的方法移到新小部件的构建函数中
    3. 向构造函数添加参数

    这样当每个FlipButton 都有自己的isReal 变量时。

    注意:我没有尝试编译它,所以可能会有一些错误。

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:audioplayers/audioplayers.dart';
    
    class Screen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            backgroundColor: Colors.teal[100],
            body: SafeArea(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  //replace all occurances on `buildButton` method with new widget
                  FlipButton(sound: 'cat.mp3', color: Colors.red, simpleImage: 'images/cat.png', realImage: 'images/cat_real.jpg'),
                  Expanded(
                      child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[
                    FlipButton(sound: 'dog.mp3', color: Colors.yellow, simpleImage: 'images/dog.png', realImage: 'images/cow.png'),
                    FlipButton(sound: 'cow.mp3', color: Colors.orange, simpleImage: 'images/cow.png', realImage: 'images/dog.png'),
                  ])),
                  Expanded(
                      child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[
                    FlipButton(sound: 'pig.mp3', color: Colors.green, simpleImage: 'images/pig.png', realImage: 'images/elephant.png'),
                    FlipButton(sound: 'elephant.mp3', color: Colors.teal, simpleImage: 'images/elephant.png', realImage: 'images/rooster.png'),
                    FlipButton(sound: 'rooster.mp3', color: Colors.blue, simpleImage: 'images/rooster.png', realImage: 'images/pig.png'),
                  ])),
                  Expanded(
                      child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: <Widget>[
                      FlipButton(sound: 'goat.mp3', color: Colors.purple, simpleImage: 'images/goat.jpg', realImage: 'images/pig.png'),
                    ],
                  )),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    
    /// You can copy this widget into separate file for better formatting
    /// 
    class FlipButton extends StatefulWidget {
      //declare final variables
      final String sound;
      final Color color;
      final String simpleImage;
      final String realImage;
    
      //constructor for this class
      const FlipButton({
        Key? key,
        required this.sound,
        required this.color,
        required this.simpleImage,
        required this.realImage,
      }) : super(key: key);
    
      @override
      _FlipButtonState createState() => _FlipButtonState();
    }
    
    class _FlipButtonState extends State<FlipButton> {
      //inside the state declare variable that is about to change
      bool isReal = false;
    
      @override
      Widget build(BuildContext context) {
        return Expanded(
            child: FlatButton(
          onPressed: () {
            setState(() {
              isReal = !isReal;
            });
            final player = AudioCache();
            player.play(sound);
          },
          color: widget.color,
          child: isReal ? Image.asset(widget.simpleImage) : Image.asset(widget.realImage),
        ));
      }
    }
    
    

    【讨论】:

    • 感谢您的建议,但我不确定如何将按钮组件移动到有状态的小部件中。 (我试着把我写的Statefull Widget代码贴在这里,但是太长了。)请问可以提供具体的代码示例吗?
    • @KN 我已经更新了答案。看看吧。
    • 我按照您制作的示例进行了编码,并为每个按钮添加了变量(即 isRealCat、isRealDog、isRealCow 等)。终于成功了!非常感谢!
    【解决方案2】:

    您可以使用 dart:math 中的 Random 类来生成下一个随机图像。 例子:

      int imageNumber = 1;
      void updateImage() {
        setState(() {
      //Random.nextInt(n) returns random integer from 0 to n-1
          imageNumber = Random().nextInt(7) + 1;
        });
      }
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Expanded(
            child: Padding(
              padding: const EdgeInsets.all(50.0),
              child: FlatButton(
                child: Image.asset('images/dice$imageNumber.png'),
                onPressed: () {
                  updateImage();
                },
              ),
            ),
          ),
        );
      }
    

    【讨论】:

    • 感谢您的 cmets,但我想做的是您更改您选择的图像。问题是当我点击多个图像的图像时,所有图像都会更改。
    猜你喜欢
    • 2022-07-25
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多