inkwell onTap is not working inside container - flutter

i'm trying to make a gallery app. i want a picture to open individually when tapped. but when I tap on a picture inkwell animation occurs but the new page doesn't open. i have defined second page in routes
Here is the code of landing page
class _ImageViewState extends State<ImageView> {
#override
Widget build(BuildContext context) {
return Container(
child: PhotoView(
maxScale: 600.0,
minScale: 200.0,
imageProvider: AssetImage("assets/mountain1.jpg",),
)
);
}
}
and this is the code where I'm calling the above class
child: InkWell(
onTap: () => {const ImageView()},
child: Image.asset('assets/mountain1.jpg', fit: BoxFit.fill,)),

Inside
OnTap method
you can only add functionality things, you can't load widget like that. if you try to load.
Or please provide more information here.

this is how you can open new page
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ImageView()),
);

Related

ScaffoldMessenger.of(context).showSnackBar() doesn't work when called directly inside a widget build function

While looking for examples for using flutter SnackBar with ScaffoldMessenger, I only found usages with onPressed function:
Widget build(BuildContext context) {
return Container(
child: ElevatedButton(
child: ...,
onPressed: () => _showToast(context),
));
}
void _showToast(BuildContext context) {
final scaffold = ScaffoldMessenger.of(context);
scaffold.showSnackBar(
SnackBar(content: const Text('Added to favorite')),
);
}
}
but non of the examples explain why one have to use it with onPressed only,
so I tried it my self and used in directly inside the build function:
Widget build(BuildContext context) {
_showToast(context); <---
return Container(
child: ElevatedButton(
...,
));
}
but than I got this error:
and I am not sure why this it happening.
I ended up giving Scaffold a key and using the GlobalKey<ScaffoldState> approach, but I really want to understand why using ScaffoldMessenger.of(context).showSnackBar() without a callback\onPressed didn't work
while ScaffoldMessenger.of(context) we need to give some time to be rendered properly(for full Scaffold). we can know the time from addPostFrameCallback. Also if you try to show the middle of widgets, the 1st portion will render but rest widgets will face this issue.
here is the soulution on build method.
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
_showToast(context);
});
to understand the concept properly we can do something like this.
Scaffold(
body: Container(
height: 100,
color: Colors.cyanAccent,
child: Column(
children: [
Text("This text will render "),
Builder(builder: (context) {
_showToast(context);
///but you will be able to see Message
return Text("it will cause error");
}),
Text("This text will not render "),
],
),
),
);
Try to add or declare your snackbar inside Future.deleayd
Future.delayed(Duration.zero, () async {
yourSnackBarFunction();
});
In Flutter build function is called by the framework itself whenever a widget needs to be rebuilt. It can occur many times!
On the other hand, you usually want to display a toast / snackbar when you want to inform your user about something. So you can display a snackbar from onPressed and many other places, but the build function itself is only for building a widget, and not responding directly to user actions.

Every time I open my preview screen or return back to it then the images in it takes 1-2 seconds to load image again

I am having a game preview screen where I have a stateless widget for scaffold and all and then a secondary stateless widget to show preview for each game. But when I open this preview page then all 3 of my preview images take sometime to load the image and when I tap the preview I can play the game and after returning from the game it again rebuild/ loads the preview images.
class Games extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Games",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 25.0),),
),
body: SingleChildScrollView(
child: Column(
children: [
GamePreviewScreen(index: 0,),
GamePreviewScreen(index: 1,),
GamePreviewScreen(index: 2,),
],
),
),
);
}
}
Stateless widget for preview:-
class GamePreviewScreen extends StatelessWidget {
final int index;
String imagePath='';
GamePreviewScreen({this.index,});
String getPath()
{
if(index==0)
return 'images/EgyptGame/preview.png';
else if(index==1)
return 'images/EgyptGame/preview.png';
else
return 'images/EgyptGame/preview.png';
}
openGame(BuildContext context)
{
if(index==0)
Navigator.push(context, MaterialPageRoute(builder: (context)=>HomePageForGame2()));
else if(index==1)
Navigator.push(context, MaterialPageRoute(builder: (context)=>HomePageForGame2()));
else
Navigator.push(context, MaterialPageRoute(builder: (context)=>HomePageForGame2()));
}
#override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: (){openGame(context);},
child: Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(color: Colors.cyan[200],width: 5),
),
child: Image.asset(getPath(),fit: BoxFit.fill,),
),
);
}
}
Have a look on your image size, dimensions and save it in jpg format it will load pretty fast.
Either convert your widgets to StatefulWidget or add a GlobalKey to Scaffold in Games page and GestureDetector of GamePreviewScreen
You can use a caching structure.
In addition, when using debug mode, a slower and more tiring experience is offered. This problem may disappear if you run your application in release mode.
Try flutter run --release in the terminal maybe you are running your app in the debug mode. It's way slower if you run the app in this mode because it has some features

Is there any solution to make my Flare Button work properly? Flutter

Basically, I have a button that I made in Flare and it should make an animation then I tap it! It works well but the animation starts everytime I tap anywhere within my app and not only the button.
Is there any way I can make animation only when I click in the Button Area? I`m using GestureDetector to handle tapping.
https://i.stack.imgur.com/ZBjmz.jpg
My code:
import 'package:flutter/material.dart';
import 'package:flare_flutter/flare_actor.dart';
import 'package:vibrate/vibrate.dart';
void main() => runApp(MaterialApp(
home: InvalidButton(),
));
class InvalidButton extends StatefulWidget {
#override
_InvalidButtonState createState() => _InvalidButtonState();
}
class _InvalidButtonState extends State<InvalidButton> {
var _type = FeedbackType.heavy;
final FlareControls controls = FlareControls();
void _playAnimation(){
controls.play('invalid');
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.pink[50],
body: Container(
child: GestureDetector(
onTap: () {
setState(() {
_playAnimation();
Vibrate.feedback(_type);
});
},
child: FlareActor(
'assets/invalid_button.flr',
animation: 'invalid',
alignment: Alignment.center,
fit: BoxFit.contain,
controller: controls,
),
),
),
);
}
}
I`m a newbie so will be glad to any help!
Do you have space around the button in the Rive editor ? If so, go in design mode, click Artboard and then "fit contents". That should remove the extra space. Then, wrap your FlareActor with a SizedBox and set its size, like so :
SizedBox(
width: 100,
height: 100,
child: FlareActor(),
)
That should do it.

modalBottomSheet is overlapped up by the keyboard

It's written here That
/// The scaffold will expand to fill the available space. That usually
/// means that it will occupy its entire window or device screen. When
/// the device's keyboard appears the Scaffold's ancestor [MediaQuery]
/// widget's [MediaQueryData.viewInsets] changes and the Scaffold will
/// be rebuilt. By default the scaffold's [body] is resized to make
/// room for the keyboard.
According to this if there is a TextField at the bottom, the Scaffold will resize itself and it does happen. But when I put a TextField inside a modalBottomSheet it doesn't get pushed up by the keyboard. The Keyboard overlaps the modalBottomSheet (with the TextField). If the Scaffold itself gets resized how modalBottomSheet stays at its place? And resizeToAvoidBottomInsethas no effect on modalBottomSheet.
Here is the sample code.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context, builder: (context) => ShowSheet());
},
),
);
}
}
class ShowSheet extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
child: TextField(
autofocus: true,
),
);
}
}
I apologize if this question is dumb but I didn't understand this.
I still don't know the reason may be because modalBottomSheet is using PopupRoute so it's a different route not sure. Anyway, here I found the solution I just needed to put some bottom viewInsets padding.
Widget build(BuildContext context) {
return Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
color: Colors.blue,
height: 200,
child: TextField(
autofocus: true,
),
),
);
}
Also I needed to set isScrollControlled: true, of showModalBottomSheet()

Navigator gets the wrong context

I have a flutter application which shows a camera, then scans a qr-code using git://github.com/arashbi/flutter_qrcode_reader and on the call back, I want to navigate to another screen to show the information I get from some query. The problem is, it seems Navigator get a wrong context, so instead of full page navigation, I see the second page pushed inside my first page as a widget.
The build of first page is as follow :
#override
Widget build(BuildContext context) {
Widget main =
new Scaffold(
appBar: _buildAppBar(),
body: Column(
children: <Widget>[
_eventButton ?? new Text(""),
new Center(
child: new Text("Hi"))
],
),
floatingActionButton: new FloatingActionButton(
onPressed:
() {
new QRCodeReader()
.setAutoFocusIntervalInMs(200)
.setForceAutoFocus(true)
.setTorchEnabled(true)
.setHandlePermissions(true)
.setExecuteAfterPermissionGranted(true)
.scan().then((barcode) => _showTicketPage(barcode));
}
,
child: new Icon(Icons.check),
),
);
if (!_loading) {
return main;
} else {
return new Stack(
children: [main,
new Container(
decoration: new BoxDecoration(
color: Color.fromRGBO(220, 220, 220,
0.3) // Specifies the background color and the opacity
),
child: new Center(child: new CircularProgressIndicator(),))
]
);
}
}
The 'Hi' Widget is for debugging, and the navigate method is
void _showTicketPage(var barcode) {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) => TicketScreen(barcode)));
}
After getting the barcode, the second screen - TicketScreen - is pushed under 'Hi' Widget. I didn't even know this was possible to do.
I tried to get the context of the screen, save it to a field var, but that didn't help either.
How can I fix it? I ran out of ideas.