Flutter : 我想在你点击图片的时候改变一张图片,其他人不受点击的影响

Flutter : I want to change an image when you tap the image, and others are not affected by the tap

我正在用 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),
    ));
  }
}

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

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

更新: 显然你应该看一些关于如何自己制作的教程。但就目前而言,这是分离小部件后的样子。

我在这里做的是:

  1. 创建新小部件classFlipButton
  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),
    ));
  }
}

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

  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();
            },
          ),
        ),
      ),
    );
  }