Home > Net >  How to display a different image when an image is clicked?
How to display a different image when an image is clicked?

Time:02-06

I'm trying to make it so that when you click on a picture, it changes to another. I tried doing this but it doesnt work-

class PopScreen extends StatefulWidget {
  final int id;
  const PopScreen({Key? key, required this.id}) : super(key: key);

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

class _PopScreenState extends State<PopScreen> {
  @override
  Widget build(BuildContext context) {
    String currentPath = normalPaths[widget.id];
    return Scaffold(
        appBar: AppBar(
          backgroundColor: animalColorThemes[widget.id],
          title: Text(
            animalData[widget.id][0],
          ),
          centerTitle: true,
        ),
        body: GestureDetector(
          onTap: () {
            setState(() {
              currentPath = activePaths[widget.id];
            });
          },
          child: Stack(
            children: [
              Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    fit: BoxFit.fill,
                    image: AssetImage(
                      currentPath,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ));
  }
}


The image is based on the integer id that gets passed into this. The problem is probably that i'm doing normalPath[widget.id] before returning the widget, so when it set states, it turns into the normalPath right after turning into the activaPath. How i find my around around this?

CodePudding user response:

This happens because everytime you rebuild your widget, you set currentPath to normalPaths[widget.id] since you set currentPath = normalPaths[widget.id]; in the first line in your build method. To fix your issue you have to move currentPath outside the build method.

class _PopScreenState extends State<PopScreen> {
  late String currentPath;
  
  @override
  void initState(){
    currentPath =  normalPaths[widget.id];
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: animalColorThemes[widget.id],
          title: Text(
            animalData[widget.id][0],
          ),
          centerTitle: true,
        ),
        body: GestureDetector(
          onTap: () {
            setState(() {
              currentPath = activePaths[widget.id];
            });
          },
          child: Stack(
            children: [
              Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    fit: BoxFit.fill,
                    image: AssetImage(
                      currentPath,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ));
  }
}

CodePudding user response:

TLDR; Declare currentPath in the class instead of the build method like so:

class _PopScreenState extends State<PopScreen> {
 late String currentPath;
 @override
 void initState(){
   currentPath = normalPaths[widget.id];
   super.initState();
 }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: animalColorThemes[widget.id],
          title: Text(
            animalData[widget.id][0],
          ),
          centerTitle: true,
        ),
        body: GestureDetector(
          onTap: () {
            setState(() {
              currentPath = activePaths[widget.id];
            });
          },
          child: Stack(
            children: [
              Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    fit: BoxFit.fill,
                    image: AssetImage(
                      currentPath,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ));
  }

setState calls the build method and having currentPath = normalPaths[widget.id]; in the build method means, currentPath would be set to normalPaths[widget.id]; everytime setState is called.

So changing the scope of currentPath from the build method to the class would fix the issue.

  •  Tags:  
  • Related