I'm trying to create a button which will do some action when pressed, suppose it calls a function _pressedButton() also if the user taps on it (or taps and hold), the image changes.
Consider this like a button with a custom picture on pressed.
In the follow-up, can I also change the image based on some external factor?
eg. if some function A returns true, show image 1, else show image 2
You can learn all about buttons and state in the Flutter interactivity tutorial.
For example, here is a button that shows a different cat every time each time it is clicked.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new HomePage(),
));
}
class HomePage extends StatefulWidget {
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> {
String _url = getNewCatUrl();
static String getNewCatUrl() {
return 'http://thecatapi.com/api/images/get?format=src&type=jpg&size=small'
'#${new DateTime.now().millisecondsSinceEpoch}';
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Cat Button'),
),
body: new Center(
child: new FloatingActionButton(
onPressed: () {
setState(() {
_url = getNewCatUrl();
});
},
child: new ConstrainedBox(
constraints: new BoxConstraints.expand(),
child: new Image.network(_url, fit: BoxFit.cover, gaplessPlayback: true),
),
),
),
);
}
}
A handy way to achieve what you want is by using GestureDetector()
GestureDetector(
onTap: () {
//desired action command
},
child: Container(
alignment: Alignment.center,
width: 100,
height: 100,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset('assets/icons/user.png'),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Colors.teal,
),
),
),
Result:
GestureDetector() basically mimics a button.
Related
List item
Trying to make a button-based off an image of a dog, that when clicked, spawns a png of a new dog. Got the button working but nothing I try will make the new dog show up. I've looked over my code tons of times and don't see whats wrong with it. Any help would be massively appreciated.
the code in question
child: FlatButton(
padding: EdgeInsets.all(0.0),
onPressed: () {
debugPrint('button clicked');
Image.asset(display);
},
child: null,
),
),
),
),
),
);
}
}
You have the Image.asset(display) assigned to nothing.
You need to replace the child: null by child: display != null ? Image.asset(display) : null
Also, you need to call the answerQuestion method inside the onPress
You need to have state and to change state use basically setState((){}) method
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
final String display1 = 'assets/doggy.png';
final String display2 = 'assets/poochie.png';
bool isFirstImage=true;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Demo 006'),),
body: Center(
child: ClipOval(
child: Container(
width: 220.0,
height: 220.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(isFirstImage?display1:display2),
),
),
child: FlatButton(
padding: EdgeInsets.all(0.0),
onPressed: () {
setState((){isFirstImage=!isFirstImage;});
},
child: null,
),
),
),
),
),
);
}
}
I'd like to perform some interaction:
when an initial touch (onTapDown) happens (e.g. clear existing selections), AND
when a double tap happens (onDoubleTap) happens (e.g. highlight a new selection)
Using a GestureDetector:
if only register a onTapDown, the callback is called immediately at the first touch
if I register both onTapDown and onDoubleTap, and the user performs a simple tap, it takes some considerable time until the onTapDown event is called (1/2 a second?). If I update the display following the tap, for the user, this feels like rendering jank -- but it in fact just getting the event to late.
Is there a way to eagerly receive onTapDown AND onDoubleTap? (Its OK, in fact preferred, if I get 2 events on a double tap).
import 'package:flutter/material.dart';
// 1. double tap the green box
// 2. single tap the green box again and that it takes a long
// time to update the text
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Playground',
home: Material(child: SafeArea(child: content())));
Widget content() {
final controller = TextEditingController(text: "-");
return Center(
child: Column(children: [
GestureDetector(
onTapDown: (_) {
controller.text = "tap down";
// print("[${DateTime.now().millisecondsSinceEpoch}] tap down");
},
onDoubleTap: () {
controller.text = "double tap ";
// print("[${DateTime.now().millisecondsSinceEpoch}] double tap");
},
child: Container(
color: Colors.green,
width: 200,
height: 200,
child: Center(child: Text("Tap me")))),
Container(
color: Colors.red,
width: 200,
height: 200,
child: Center(child: TextField(controller: controller)))
]));
}
}
main() => runApp(MyApp());
A hacky way to do it I suppose, but you can use a Listener for onPointerDown. The code below should log tap down twice when you double-tap:
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) => MaterialApp(title: 'Flutter Playground', home: Material(child: SafeArea(child: content())));
Widget content() {
final controller = TextEditingController(text: "-");
return Center(
child: Column(
children: [
GestureDetector(
onDoubleTap: () {
controller.text = "double tap";
print("double tap");
},
child: Listener(
onPointerDown: (_) {
controller.text = "tap down";
print("tap down");
},
child: Container(
color: Colors.green,
width: 200,
height: 200,
child: Center(
child: Text("Tap me"),
),
),
)),
Container(
color: Colors.red,
width: 200,
height: 200,
child: Center(
child: TextField(controller: controller),
),
)
],
),
);
}
}
main() => runApp(MyApp());
Use gesture_x_detector plugin.
XGestureDetector(
bypassTapEventOnDoubleTap: true,
doubleTapTimeConsider: 170
child: ...
)
I have issue with the Raised button click. The method inside OnPressed() is not getting called. Ideally on the OnPressed() method i would like to have the pop up or a slider shown. I have created the example to show the problem currently faced.
The main.dart file calls Screen2()
import 'package:flutter/material.dart';
//import 'package:flutter_app/main1.dart';
import 'screen2.dart';
void main() => runApp(Lesson1());
class Lesson1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Screen2(),
);
}
}
and in Screen2()i have just have a RaisedButton and OnPressed() it needs to call the function ButtonPressed().
import 'package:flutter/material.dart';
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text('Screen 2'),
),
body: Center(
child: RaisedButton(
color: Colors.blue,
child: Text('Go Back To Screen 1'),
onPressed: () {
print('centrebutton');
ButtonPressed();
},
),
),
);
}
}
class ButtonPressed extends StatefulWidget {
#override
_ButtonPressedState createState() => _ButtonPressedState();
}
class _ButtonPressedState extends State<ButtonPressed> {
#override
Widget build(BuildContext context) {
print ('inside button press');
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text('Screen 3'),
),
// create a popup to show some msg.
);
}
}
On clicking the Raised button the print statement ('centerbutton') gets printed.
But the ButtonPressed() method is not getting called .
I am not able to see the print msg('inside button press') in the console. Pl. let me what could be the reason for ButtonPressed method not getting called. Attached the snapshot for your reference.
You are calling a Widget on your RaisedButton's onPressed method. Your widget is getting called but will not render anywhere in the screen.
You should call a function for processing your data in a tap event. But you are calling a widget or say a UI view.
If you want to navigate to the respective screen then you should use navigator.
For ex :
onPressed: () {
print('centrebutton');
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => ButtonPressed()));
},
This could be a cause: If you have an asset as a child of your button, and that asset does not exist, the button onpressed will not work.
Solution: remove the asset.
Example:
return RaisedButton(
splashColor: Colors.grey,
onPressed: () {
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("assets/google_logo.png"), height: 35.0), //remove this line
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
)
],
),
),
);
I want to add an image and a text together in a card but I'm not able to do it. I think a row would be used here but not able to implement it. I'm new to flutter and app development so having some troubles. Any help is really appreciated. Also the cards are in GridView(not in ListView).
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'lists.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Just Another App',
home: Home(),
routes: {
"/webview": (_) => WebviewScaffold(
withJavascript: true,
withLocalStorage: true,
url: 'https://www.google.com/',
appBar: AppBar(
title: Text('Browser'),
),
),
},
theme: ThemeData(primaryColor: Colors.black),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final webView = FlutterWebviewPlugin();
#override
void initState() {
super.initState();
webView.close();
}
#override
Widget build(BuildContext context) {
var gridView = GridView.builder(
itemCount: 15,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return InkWell(
child: Card(
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(35),
child: Container(
// child: SizedBox(child: Text('yashjha'),),
// child: Image.asset('lib/images/${images[index]}'),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('lib/images/${images[index]}'),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
),
),
onTap: () {
setState(() {
Navigator.of(context).pushNamed('/webview');
});
},
);
});
return Scaffold(
appBar: AppBar(
title: Text('Just Another App'),
),
body: Container(
child: gridView,
padding: EdgeInsets.all(12),
),
);
}
[GridViewApp Screenshot][1]}
This is a variable which I'm using in the "body" of Scaffold.
If you want to place an Image and a text side by side, add a Row widget:
child: Row(
children: <Widget>[
DecorationImage(...),
Text(...),
],
)
You can also set mainAxisAlignment and crossAxisAlignment to make sure that your widgets are placed correctly
just wrap your Container into a Row Widget and add a text to it.
Row(
children: <Widget>[
Text("add text here"),
Container(
// child: SizedBox(child: Text('yashjha'),),
// child: Image.asset('lib/images/${images[index]}'),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('lib/images/${images[index]}'),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
],
),
Working on an App that will require multiple screens. The below right now shows only two icons, more later, and i need them the be able to go the a corresponding screen when pressed. Everything works but the onPressed function. The error I get is
The named parameter "onPressed" is not defined
Do I have the onPressed function in the wrong spot? I have tried moving it between other functions but I get the same error.
Any help is appreciated
main.dart
import 'package:flutter/material.dart';
import './food_screen.dart';
void main(List<String> args) {
runApp(new MaterialApp(
home : MyApp(),
));
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title :Text('Main Title'),
backgroundColor: Colors.blue,
),
backgroundColor: Colors.blue[100],
body: Container(
padding: EdgeInsets.all(30.0),
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Card(
margin: EdgeInsets.all(8.0),
child: InkWell(
onTap: (){
Navigator.push(context,
MaterialPageRoute(builder: (context)=>FoodScreen())
);
},
splashColor: Colors.blue,
child: Center(
child: Column(
children: <Widget>[
Icon(Icons.fastfood, size: 70.0),
Text("FOOD", style: new TextStyle(fontSize: 28.0))
]
)
),
),
),
Card(
margin: EdgeInsets.all(8.0),
child: InkWell(
onTap: (){},
splashColor: Colors.blue,
child: Center(
child: Column(
children: <Widget>[
Icon(Icons.directions_car, size: 70.0),
Text("VEHILCES", style: new TextStyle(fontSize: 28.0))
],
),
),
),
),
]
)
)
);
}
}
food_screen.dart
import 'package:flutter/material.dart';
import './main.dart';
class FoodScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
);
}
}
Card doesn't support onPressed property, you already have InkWell which has onTap, you can put onPressed method action inside it.
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context)=>FoodScreen())
);
}
Card doesn't have any property of onpressed()
you can add a floating button and Route it to the the second page i.e food_screen.dart
https://api.flutter.dev/flutter/material/Card-class.html
if you want to add a tap on Card Widget just wrap the card with GestureDetector.