Flutter - GestureDetector - onTap: widget.press(), - final Function press;- Navigator.of(context).push();

153 views Asked by At

This is my first page (RecomendsPlants) and I want to move to another page called (DetailsScreen)

RecomendsPlants:



// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';

import 'package:mr_plants_store/constants.dart';

import 'package:mr_plants_store/screens/details/details_screen.dart';

class RecomendsPlants extends StatefulWidget {

const RecomendsPlants({super.key});

@override

State\ createState() =\> \_RecomendsPlantsState();

}

class \_RecomendsPlantsState extends State\ {

@override

Widget build(BuildContext context) {

return SingleChildScrollView(

scrollDirection: Axis.horizontal,

child: Row(

children: \[

RecomendedPlantCard(

country: "Russia",

image: "assets/images/image_1.png",

press: () {

Navigator.of(context).push(MaterialPageRoute(builder: (context) {

return const DetailsScreen();

}));

},

price: 448,

title: "Samantha",

),

RecomendedPlantCard(

country: "Russia",

image: "assets/images/image_2.png",

press: () {

Navigator.of(context).push(MaterialPageRoute(builder: (context) {

return const DetailsScreen();

}));

},

price: 448,

title: "Samantha",

),
RecomendedPlantCard(

country: "Russia",

image: "assets/images/image_3.png",

press: () {

Navigator.of(context).push(MaterialPageRoute(builder: (context) {

return const DetailsScreen();

}));

},

price: 448,

title: "Samantha",

),

\],

),

);

}

}

class RecomendedPlantCard extends StatefulWidget {

const RecomendedPlantCard(

{super.key,

required this.image,

required this.title,

required this.country,

required this.price,

required this.press});

final String image, title, country;

final int price;

final Function press;

@override

State\ createState() =\> \_RecomendedPlantCardState();

}

class \_RecomendedPlantCardState extends State\ {

@override

Widget build(BuildContext context) {

Size size = MediaQuery.of(context).size;

return Container(

margin: EdgeInsets.only(

left: kDefaultPadding,

top: kDefaultPadding / 2,

bottom: kDefaultPadding,

),

width: size.width \* 0.4,

child: Column(

children: \[

Image.asset(widget.image),

GestureDetector(

onTap: widget.press(),

child: Container(

padding: EdgeInsets.all(kDefaultPadding / 2),

decoration: BoxDecoration(

color: Colors.white,

borderRadius: BorderRadius.only(

bottomLeft: Radius.circular(10),

bottomRight: Radius.circular(10)),

boxShadow: \[

BoxShadow(

offset: Offset(0, 10),

blurRadius: 10,

color: kPrimaryColor.withOpacity(0.1),

),

\]),

child: Row(

children: \[

RichText(

text: TextSpan(

children: \[

TextSpan(

text: "${widget.title}\\n".toUpperCase(),

style: Theme.of(context).textTheme.button,

),

TextSpan(

text: widget.country.toUpperCase(),

style: TextStyle(

color: kPrimaryColor.withOpacity(0.5),

),

),

\],

),

),

Spacer(),

Text(

"$${widget.price}",

style: Theme.of(context)

.textTheme

.button

?.copyWith(color: kPrimaryColor),

),

\],

),

),

)

\],

),

);

}

}

DetailsScreen:



// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';

import 'package:mr_plants_store/screens/details/components/body.dart';

class DetailsScreen extends StatefulWidget {

const DetailsScreen({super.key});

@override

State\ createState() =\> \_DetailsScreenState();

}

class \_DetailsScreenState extends State\ {

@override

Widget build(BuildContext context) {

return Scaffold(

body: Body(),

);

}

}

class Body extends StatefulWidget {

const Body({super.key});

@override

State\ createState() =\> \_BodyState();

}

class \_BodyState extends State\ {

@override

Widget build(BuildContext context) {

return Container(

child: Text("next Page"),

);

}

}

And I cant move to other page because of this Error:

════════ Exception caught by widgets library ═══════════════════════════════════ 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4475 pos 12: '!_debugLocked': is not true. package:flutter/…/widgets/navigator.dart:4475 The relevant error-causing widget was RecomendedPlantCard

I tried all types of Navigator.of(context).push(MaterialPageRoute(builder: (context) {

return const DetailsScreen();

}));

but nothing work

I tried :



GestureDetector(

onTap: (){

Navigator.of(context).push(MaterialPageRoute(builder: (context) {

return const DetailsScreen();

}));

},

child:());

also not working

So Please help !!!!!!

2

There are 2 answers

0
CCP On BEST ANSWER

Change this onTap: widget.press() to onTap:() => widget.press()

1
timyau On

The problem is here, the press() {}. When you run this code, the page will run as soon as possible to navigate to your DetailsScreen().

RecomendedPlantCard(
            country: "Russia",
            image: "assets/images/image_1.png",
            press: () {
              Navigator.of(context).push(MaterialPageRoute(builder: (context) {
                return const DetailsScreen();
              }));
            },
            price: 448,
            title: "Samantha",
          ),

When you pass the callback press: () { Navigator.of(context).push(MaterialPageRoute(builder: (context)=> const DetailsScreen())); } to the RecomendedPlantCard widget and inside the build method, it will be called every time the RecomendsPlants or RecomendedPlantCard widget rebuilds.

Every time RecomendsPlants or RecomendedPlantCard widget rebuilds, the press callback will be called again which will try to push the same route again and again on the navigation stack. This can cause issues such as unexpected navigation behavior and memory leaks.

To fix this issue, you should move the logic of pushing the route outside the build method, You can pass context and MaterialPageRoute inside the constructor of the RecomendedPlantCard and navigate inside the press method of _RecomendedPlantCardState .