悬停按钮上随机 Image.asset 变化?

Flutter random Image.asset changes on hovering Button?

我想在用户每次进入页面时随机显示一张图片。我在这个页面上还有一个按钮(带有悬停的红色容器),当用户悬停它时,会显示一张新的随机图片,但自页面加载后它不应该改变。我认为这与 setState() 有关,但我不知道该怎么做。代码:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:core';
import 'dart:math';


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

  @override
  _Home2State createState() => _Home2State();
}

class _Home2State extends State<Home2> {
  dynamic listCinematicImages = [
    "assets/cinematic/1.jpg",
    "assets/cinematic/2.jpg",
    "assets/cinematic/3.jpg",
    "assets/cinematic/4.jpg",
    "assets/cinematic/5.jpg",
    "assets/cinematic/6.jpg",
    "assets/cinematic/7.jpg",
  ];
  late Random rnd;

  @override
  
  bool isHoveringButton = false;
  
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.black,
      body: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            height: double.infinity,
            width: size.width * 0.5,
            alignment: Alignment.center,
            child: InkWell(
              onTap: () {

              },
              onHover: (hovering) {
                setState(() => isHoveringButton = hovering);
              },
              child: Container(
                height: 50,
                width: 50,
                color: Colors.red,
              ),
            ),
          ),
          Container(
            height: double.infinity,
            width: size.width * 0.5,
            child: img(),
          ),
        ],
      ),
    );
  }

  Image img() {
    int min = 0;
    int max = listCinematicImages.length-1;
    rnd = new Random();
    int r = min + rnd.nextInt(max - min);
    String image_name  = listCinematicImages[r].toString();
    return Image.asset(image_name, fit: BoxFit.cover,);
  }
}

我不知道这是否有帮助,但这是给出的一些错误:

Error: Expected a value of type 'Map<String, dynamic>', but got one of type 'Null'
    at Object.throw_ [as throw] (http://localhost:60569/dart_sdk.js:5054:11)
    at Object.castError (http://localhost:60569/dart_sdk.js:5013:15)
    at Object.cast [as as] (http://localhost:60569/dart_sdk.js:5336:17)
    at Function.as_C [as as] (http://localhost:60569/dart_sdk.js:4959:19)

好的,这里发生了很多事情。让我们一步一步地考虑这个问题。您正试图在某些事件中展示新形象。所以我们需要创建一个变量来跟踪当前图像:

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

  @override
  _Home2State createState() => _Home2State();
}

class _Home2State extends State<Home2> {
  static const listCinematicImages = [
    "assets/cinematic/1.jpg",
    "assets/cinematic/2.jpg",
    "assets/cinematic/3.jpg",
    "assets/cinematic/4.jpg",
    "assets/cinematic/5.jpg",
    "assets/cinematic/6.jpg",
    "assets/cinematic/7.jpg",
  ];

 late String currentImage;
    
}

在我们开始担心事件之前,让我们弄清楚如何从您的列表中 select 随机图像。您提供的功能具有正确的元素,但发生了一些奇怪的事情。我举的一个简单例子是:

String _getRandomImage() {
  final randomIndex = Random().nextInt(listCinematicImages.length-1);
  return listCinematicImages[randomIndex];
}

现在我们拥有所有元素,我们只需要在正确的时间更新小部件。首先你想在每次加载这个小部件时设置一个新图像。我们可以使用 initState 方法来做到这一点:

@override
void initState() {
  super.initState();

  final newImage = _getRandomImage();
  setState(() => currentImage = newImage);
}

并且您想在用户将鼠标悬停在图像上时再次更改图像。您确实可以使用 InkWell 执行此操作,但请记住,根据 documentation,每次鼠标进入和离开该区域时,onHover 都会提供回调,因此我们必须确保仅在我们进入区域时更新图像:

InkWell(
  onHover: (bool hasEntered) {
    if(!hasEntered) return;
    
    final newImage = _getRandomImage();
    setState(() => currentImage = newImage);
  }
);

就是这样!将它们与您的示例放在一起:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:core';
import 'dart:math';


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

  @override
  _Home2State createState() => _Home2State();
}

class _Home2State extends State<Home2> {
  static const listCinematicImages = [
    "assets/cinematic/1.jpg",
    "assets/cinematic/2.jpg",
    "assets/cinematic/3.jpg",
    "assets/cinematic/4.jpg",
    "assets/cinematic/5.jpg",
    "assets/cinematic/6.jpg",
    "assets/cinematic/7.jpg",
  ];

  late String currentImage;

  @override
  void initState() {
    super.initState();

    final newImage = _getRandomImage();
    setState(() => currentImage = newImage);
  }


  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.black,
      body: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            height: double.infinity,
            width: size.width * 0.5,
            alignment: Alignment.center,
            child: InkWell(
              onHover: (bool hasEntered) {
                if(!hasEntered) return;

                final newImage = _getRandomImage();
                setState(() => currentImage = newImage);
              },
              child: Container(
                height: 50,
                width: 50,
                color: Colors.red,
              ),
            ),
          ),
          Container(
            height: double.infinity,
            width: size.width * 0.5,
            child: Image.asset(currentImage, fit: BoxFit.cover,);,
          ),
        ],
      ),
    );
  }

  String _getRandomImage() {
    final randomIndex = Random().nextInt(listCinematicImages.length-1);
    return listCinematicImages[randomIndex];
  }
}