I am trying to do this kind of thing with Flutter :
https://storage.googleapis.com/spec-host-backup/mio-design%2Fassets%2F0B3T7oTWa3HiFcHBDaTlreHdVZGc%2Fitem-selection-selecting-items.mp4
var gestureTemp = GestureDetector(
onLongPress: (){
print('LONG PRESSED');
//CHANGE APPBAR
},
child: Padding(
padding: EdgeInsets.only(right:8),
child: Chip(
avatar: CircleAvatar(
backgroundColor: Colors.grey.shade800,
child: icon
),
label: Text(space.label, style: TextStyle(fontSize: 12, color:Colors.grey.shade800))
),
));
It detects the long press, but I don't know how to change my appbar...
Any ideas ?
EDIT: Here is what I do
var appBar1 = AppBar(...);
var appBar2 = AppBar(...);
var appBar = appBar1;
My appBar is displayed in my Scaffold.
On my GestureDetector :
onLongPress: (){
print('LONG PRESSED');
setState(() {
appBar = appBar2;
});
},
Welcome to StackOverflow!
The approach you described sounds quite right. Here is a standalone example so you can double check your code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: MyPage());
}
}
class MyPage extends StatefulWidget {
#override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
static final AppBar _defaultBar = AppBar(
title: Text('Inbox'),
leading: Icon(Icons.menu),
actions: <Widget>[Icon(Icons.search), Icon(Icons.more_vert)],
backgroundColor: Colors.black,
);
static final AppBar _selectBar = AppBar(
title: Text('1'),
leading: Icon(Icons.close),
actions: <Widget>[
Icon(Icons.flag),
Icon(Icons.delete),
Icon(Icons.more_vert)
],
backgroundColor: Colors.deepPurple,
);
AppBar _appBar = _defaultBar;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appBar,
body: Center(
child: RaisedButton(
child: Text('Switch!'),
onPressed: () {
setState(() {
_appBar = _appBar == _defaultBar
? _selectBar
: _defaultBar;
});
},
),
),
);
}
}
Related
i am learning flutter and i just created an app that will update a counter variable when the user clicks on any part of the screen except the AppBar. However, the GestureDetector does not detect any clicks on the4 screen except for those on the text itself
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("i am a title"),
backgroundColor: Colors.teal,
leading: const Icon(
Icons.home,
color: Colors.white,
),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const [
Expanded(
child: Clicks(),
),
],
),
),
),
);
}
}
class Clicks extends StatefulWidget {
const Clicks({super.key});
#override
State<Clicks> createState() => _ClicksState();
}
class _ClicksState extends State<Clicks> {
int count = 0;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => setState(
() {
count++;
},
),
child: Center(
child: Text("total number of clicking on scren is $count "),
),
);
}
}
The GestureDetector will detect any gestures for it's child - in this case the Text widget.
If you want to detect everything, wrap the entrie Scaffold with a GestureDector.
In this case, you'll have to refactor your code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Clicks();
}
}
class Clicks extends StatefulWidget {
const Clicks({super.key});
#override
State<Clicks> createState() => _ClicksState();
}
class _ClicksState extends State<Clicks> {
int count = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("i am a title"),
backgroundColor: Colors.teal,
leading: const Icon(
Icons.home,
color: Colors.white,
),
),
body: GestureDetector(
onTap: () {
setState(() {
count++;
});
},
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Text("clicked a total of $count times"),
),
],
),
),
),
),
);
}
}
Try with below changes :
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => setState(
() {
count++;
},
),
child: Center(
child: Text("total number of clicking on scren is $count "),
),
);
I'm using the PopupMenuButton in flutter for a web based project and trying to change the popupmenubutton icon when it's clicked. So in its initial state it would show Icons.menu and when opened, it could would Icons.close and once clicked again revert back to Icons.menu.
I have tried onSelected which does not get called at all when clicked in an attempt to change the icon.
I have used an icon or a child IconButton per the docs and used onPressed to setState however that doesn't work either.
Currently the elevated button when clicked, does not show the dropdown menu, nor does it update the icon.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool menuClicked = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
PointerInterceptor(
intercepting: true,
child: PopupMenuButton<String>(
offset: const Offset(10.0, 50.0),
color: Colors.black,
child: ElevatedButton(
onPressed: () {
setState(() {
menuClicked = !menuClicked;
});
},
child: Icon((menuClicked = true)
? Icons.menu
: Icons.close),),
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
PopupMenuItem(
value: "close",
child: ListTile(
leading: Icon(Icons.close, color: Colors.white),
title: Text('Close',
style: TextStyle(color: Colors.white)),
onTap: () {
Navigator.pop(context);
}),
),
],
),
],
),
),
body: Center(
child: Text('test'),
),
);
}
}
Equal sign will be ==
Icon((menuClicked == true) ? Icons.menu : Icons.close),
or you can do
Icon(menuClicked ? Icons.menu : Icons.close),
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool menuClicked = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
onPanDown: (details) {
setState(() {
menuClicked = true;
});
},
child: PopupMenuButton<String>(
offset: const Offset(10.0, 50.0),
color: Colors.black,
onSelected: (value) {
setState(() {
menuClicked = false;
});
},
padding: EdgeInsets.zero,
onCanceled: () {
setState(() {
menuClicked = false;
});
},
child: Icon(menuClicked ? Icons.close : Icons.menu),
itemBuilder: (BuildContext context) => [
PopupMenuItem(
value: "close",
child: ListTile(
leading: Icon(Icons.close, color: Colors.white),
title: Text(
'Close',
style: TextStyle(color: Colors.white),
),
onTap: () {
Navigator.pop(context);
},
),
),
],
),
),
],
),
);
}
}
As you can see, I've created two FlatButton widgets and set their states to confine with the code that every time one of them is clicked, it changes color to red. But I want only one of them to turn red for each time one of them is clicked. I'm not much of a genius at this stuff as I'm just a beginner, apologies!
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Test'),
),
body: MyStatefulApp(),
),
);
}
}
class MyStatefulApp extends StatefulWidget {
#override
MyState createState() => MyState();
}
class MyState extends State<MyStatefulApp> {
bool changeColor = false;
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
FlatButton(
child: Text('TEST'),
color: changeColor ? Colors.red : Colors.blue,
onPressed: () {
setState(() {
changeColor = !changeColor;
},);
},
),
FlatButton(
child: Text('TEST'),
color: changeColor ? Colors.red : Colors.blue,
onPressed: () {
setState(() {
changeColor = !changeColor;
},);
},),
],
),
);
}
}
edit: I know that I could do that, but I'm planning on making numerous buttons in a GridView, and so I'd have to create hundreds of different variables, which is not ideal whatsoever. Any other solutions would be v appreciated
You can create a new class for each button and then instantiate it on your Column, so each button will change only its own color.
class MyButton extends StatefulWidget {
#override
_MyButtonState createState() => _MyButtonState();
final String title;
MyButton(this.title);
}
class _MyButtonState extends State<MyButton> {
bool changeColor = false;
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () {
setState(() {
changeColor = !changeColor;
},);
},
color: changeColor ? Colors.red : Colors.blue,
child: Text(widget.title)
);
}
}
Your column should look like this:
Column(
children: <Widget>[
MyButton('Button 1'),
MyButton('Button 2'),
],
)
The problem is that you are using the same variable name for both buttons. Create one variable for each button and update it on each setState.
It should look like this:
bool color1 = false;
bool color2 = false;
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
FlatButton(
child: Text('TEST'),
color: color1 ? Colors.red : Colors.blue,
onPressed: () {
setState(() {
color1 = !color1;
},);
},
),
FlatButton(
child: Text('TEST'),
color: color2 ? Colors.red : Colors.blue,
onPressed: () {
setState(() {
color2 = !color2;
},);
},
),
],
),
);
I wanted to change the color of the counter in my app. I want to do that: change the color of the counter to blue when counter bigger than 0. if counter smaller than 0 change the color of the counter to red.if counter equal to 0 change the color of the counter to green. is it possible? I did just for 2 colors.
it is my codes :
import 'package:flutter/material.dart';
void main() {
runApp(Myapp());
}
class Myapp extends StatefulWidget {
#override
_MyappState createState() => _MyappState();
}
class _MyappState extends State<Myapp> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Myhomepage(
title: "My Home Page",
),
);
}
}
class Myhomepage extends StatefulWidget {
final String title;
Myhomepage({this.title});
#override
_MyhomepageState createState() => _MyhomepageState();
}
class _MyhomepageState extends State<Myhomepage> {
int counter = 0;
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Colors.grey[850],
onPressed: () {
setState(() {
counter++;
});
}),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text(
"Increase",
),
color: Colors.green,
onPressed: () {
setState(() {
counter++;
});
},
),
Text("The count of press button:"),
Text(
"$counter",
style: Theme.of(context).textTheme.display2.copyWith(color: counter<=0 ? Colors.red : Colors.blue)
),
RaisedButton(
child: Text(
"Decrease",
),
color: Colors.red,
onPressed: () {
setState(() {
counter--;
});
},
),
],
),
),
);
}
}
it is my results :
Here's one way you can implement the system you want. I just made a function that returns the desired color.
class _MyhomepageState extends State<Myhomepage> {
int counter = 0;
Color _getCounterColor() {
if (counter > 0) return Colors.blue;
else if (counter < 0) return Colors.red;
else return Colors.green;
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Colors.grey[850],
onPressed: () {
setState(() {
counter++;
});
}),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text(
"Increase",
),
color: Colors.green,
onPressed: () {
setState(() {
counter++;
});
},
),
Text("The count of press button:"),
Text(
"$counter",
style: Theme.of(context).textTheme.display2.copyWith(color: _getCounterColor()),
),
RaisedButton(
child: Text(
"Decrease",
),
color: Colors.red,
onPressed: () {
setState(() {
counter--;
});
},
),
],
),
),
);
}
}
I have a basic question about send setState
to Second Page in the same class as this method like
_GoToNextPage(){
Navigator.of(context).push(MaterialPageRoute(builder: (context) {...})
}
The problem is when I change background color in second page it doesn't
change color in the same page But it changes the color of The prime home page.
This is the full code...
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: SetStateToSecondPage(),
));
class SetStateToSecondPage extends StatefulWidget {
#override
_SetStateToSecondPageState createState() => _SetStateToSecondPageState();
}
class _SetStateToSecondPageState extends State<SetStateToSecondPage> {
Color color = Colors.deepPurpleAccent;
bool Switch = false;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: color,
appBar: AppBar(
title: Text('setState to Second Page ?'),
elevation: 0.0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {
Switch = !Switch;
color = Switch ? Colors.white : Colors.green;
});
},
child: Text('Change Back GroundColor'),
),
RaisedButton(
onPressed: () {
_GoToNextPage(context);
},
child: Text('To Next Page..'),
),
],
),
),
);
}
//------------- This is second Page ----------//
_GoToNextPage(BuildContext context) {
return Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
backgroundColor: color,
body: Center(
child: RaisedButton(
onPressed: () {
setState(() {
color = Colors.red;
});
},
child: Text('Change Back GroundColor'),
),
),
);
}));
}
}
thanks
SetState is specific to the object you are in . and when you call it you notify the framework that the state has changed . so calling setState in _SetStateToSecondPageState will not affect Second Page so you need to create another StatefulWidget
class SecondPage extends StatefulWidget {
MaterialColor secondColor ;
SecondPage({this.secondColor});
#override
_SecondPageState createState() => new _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
backgroundColor: widget.secondColor,
body: Center(
child: RaisedButton(
onPressed: () {
setState(() {
widget.secondColor = Colors.amber;
});
},
child: Text('Change Back GroundColor'),
),
),
);
}
}
and when you call _GoToNextPage use the SecondPage constructor to change the color
_GoToNextPage(BuildContext context) {
return Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return SecondPage(
);
}));
}