I've made an app that's got a row of three buttons that when pressed are supposed to:
1) turn bold
2) change the output on the page
I've solved step 1 by doing this:
The page's class has an instance variable:
List<bool> _boldButtons = [false, true, false];
Each button's TextStyle has the fontWeight property:
fontWeight: _boldButtons[0] ? FontWeight.bold : FontWeight.normal),
And its onPresed:
onPressed: () {
setState(() {
_boldButtons = [true, false, false];
});
This feels hacky, but does the trick. If anyone has a better way of doing this I'd be more then happy to hear!
To solve problem 2) I'm thinking of doing something like this:
Make three methods (notifications(), yourRecipes(), favorites() ) that return a Container.
Have an instance variable in the page's class that is of that type:
Container wallOfText;
In each button's onPressed we set the wallOfText variable to be equal to that button's function, something like this:
onPressed: () {
wallOfText = boldButtons[0] ? wallOfText : notifications();
// ternary operator to check if we've already selected the button we're pressing, and therefore don't need to redefine what to display
setState(() {
_boldButtons = [true, false, false];
});
Then we display the wallOfText variable in the Scaffold.
This also feels really hacky, but might work. Is there a more general way of doing this?
I have changed little bit in your code, like i have take single variable which hold the selected tab value and update it on tab selection, have a look on below code for it.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
var selectedTab = 1;
var selectedText="First Tab";
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Container(
child: Column(
children: <Widget>[
Container(
color: Colors.deepOrange,
child:Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () {
setState(() {
selectedTab=1;
selectedText="First Tab";
});
},
child: Text(
"Notifications",
style: TextStyle(
fontWeight:
selectedTab == 1 ? FontWeight.bold : FontWeight.normal),
),
),
FlatButton(
onPressed: () {
setState(() {
selectedTab=2;
selectedText="Second Tab";
});
},
child: Text(
"Your recipe",
style: TextStyle(
fontWeight:
selectedTab == 2 ? FontWeight.bold : FontWeight.normal),
),
),
FlatButton(
onPressed: () {
setState(() {
selectedTab=3;
selectedText="Third Tab";
});
},
child: Text(
"Favorites",
style: TextStyle(
fontWeight:
selectedTab == 3 ? FontWeight.bold : FontWeight.normal),
),
),
],
) ,
)
,
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height*0.6,
child: Align(
alignment: Alignment.center,
child: Text(selectedText),
),
)
],
),
),
);
}
}
And please check the output of it
Related
For instance: I have a main Icon so when you click on it, it opens a pop-up window with smaller icons/images to select from. So if you select one of the pictures from that pop-up it replaces the main Icon to that specific image.
I have spent hours trying to figure out how to replace icon images but nothing seems to work.
I have created an example (I have used flutter_speed_dial to make expandable buttons but it's not necessary). You can adjust it to your needs:
class _TestState extends State<Test> {
var fabIcon = Icons.expand_less;
var button1Icon = Icons.home;
var button2Icon = Icons.shop;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: SpeedDial(
icon: fabIcon,
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(button1Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button1Icon;
button1Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(button2Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button2Icon;
button2Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
),
),
);
}
}
Using showDialog(...) is the solution.
Hope this will help you and others.
you can look at this example:
import 'package:flutter/material.dart';
class IconDialogScreen extends StatefulWidget {
const IconDialogScreen({Key? key}) : super(key: key);
#override
State<IconDialogScreen> createState() => _IconDialogScreenState();
}
class _IconDialogScreenState extends State<IconDialogScreen> {
IconData icon = Icons.abc;
List<IconData> icons = [
Icons.abc,
Icons.person_add,
Icons.person,
Icons.person_remove,
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: onIconClicked,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 20,
children: [Icon(icon, size: 50), const Text("change icon")],
),
),
)
],
),
);
}
void onIconClicked() async {
IconData? _icon = await showDialog<IconData?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select one icon'),
content: Wrap(
spacing: 10,
runSpacing: 10,
children: icons.map<Widget>((e) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).pop(e);
},
child: Icon(e, size: 50));
}).toList(),
),
);
},
);
if (_icon != null) {
setState(() {
icon = _icon;
});
}
}
}
It shows this error although I have added late and required in the Question class constructor. It's repeatedly shows
Exception caught by widgets library
The following LateError was thrown building _BodyBuilder:
LateInitializationError: Field 'ques' has not been initialized
Main class:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'QuestionsAnswers.dart';
void main() {
runApp(const Quizzler());
}
class Quizzler extends StatelessWidget {
const Quizzler({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.grey[900],
leading: Icon(Icons.games),
title: Text(
'Quizzler',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
color: Colors.white,
),
),
),
body: QuizPlay(),
),
),
);
}
}
class QuizPlay extends StatefulWidget {
const QuizPlay({Key? key}) : super(key: key);
#override
State<QuizPlay> createState() => _QuizplayState();
}
class _QuizplayState extends State<QuizPlay> {
List<Icon> score=[];// array of score icon
List<Questions>questionsAndAnswers=[
Questions(a:'Pakistan is an under developed country',b:true),
Questions(a:'Imran Khan is the Prime Minister of Pakistan',b:true),
Questions(a:'Y comes after U',b:false)
];
int questiontracker=0;// variable to increment of questions
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
questionsAndAnswers[questiontracker].ques,
style: TextStyle(
fontSize: 25.0,
color: Colors.white70,
),
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green),
),
onPressed: () {
//Yes button
bool answer=questionsAndAnswers[questiontracker].ans;
if (answer==true)
{
print('correct answer');
}
else
{
print('wrong answer ');
}
setState(() {
questiontracker++;
score.add(Icon(Icons.check,color: Colors.green,)) ;
});
},
child: Text(
'Yes',
style: TextStyle(
fontSize: 20.0,
),
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: () {
// No button
bool answer=questionsAndAnswers[questiontracker].ans;
if (answer==false)
{
print('correct answer');
}
else
{
print('wrong answer ');
}
setState(() {
questiontracker++;
score.add(Icon(Icons.close,color: Colors.red,)) ;
});
},
child: Text(
'No',
style: TextStyle(
fontSize: 20.0,
),
),
),
),
),
Row(
children: score,
),
],
);
}
}
###Question CLASS###
class Questions{
late String ques;
late bool ans;
Questions({required String a,required bool b})
{
a=ques;
b=ans;
}
}
make it
ques = a;
ans = b;
This stores the value on the right in the value on the left.
Your class constructor Questions is wrong, change it to:
class Questions{
late String ques;
late bool ans;
Questions({required String a,required bool b}) {
ques = a;
and = b;
}
}
What is the purpose of having your questions as a plain class? I'd suggest turning it into a module class which in turn should be
class Question
{
String? ques;
bool? ans;
Question({
this.ques, this.ans});
}
and when you want to initialize a question I'd suggest creating a list
List<Question> questions = [];
question.add(Question("question",true));
// add more as you wish
This will allow you to turn it into JSON which will enable you to maybe provide questions from an online database to the app without needing to update the app every time you want to add a question.
I am trying to create a favorite button for my app. Which work is to change and save color, while the user presses it,So I decided to use hive db for it.When the icon button is tapped; the color get changed,which indicates the user that its been marked as their favorite.The problem is when i tap it again(if the user wants to unmark it ) though the color get changed ,when i move to other page or hot start/reload the page, the color changed back to it former self automatically(To the color when it was first pressed).I wants the color reactive through the button and be saved.How can i solve this issue?
class p1 extends StatefulWidget {
#override
_p1State createState() => _p1State();
}
class _p1State extends State<p1> {
Box box;
bool _isFavorite = false;
_p1State();
#override
void initstate(){
super.initState();
// Get reference to an already opened box
box = Hive.box(FAVORITES_BOX);
final data = box.get(_isFavorite);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body:Stack(
children:<Widget>[
Image(
image:AssetImage("Image/Chowsun1.jpg"),
fit:BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
Align(alignment: Alignment.center,
child: Text(' Rehman '
,style: TextStyle(fontSize: 35.0,
color: Colors.white,
fontFamily: "Explora",
fontWeight: FontWeight.w900 ) )
),
Stack ( children: [Positioned(
top:90,
right: 20,
child:const Text(' 1 ',
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
fontFamily: "Comforter"
),
),
)], ),
Align(
alignment: Alignment.bottomCenter,
child: (
IconButton(
icon: Icon(
Icons.favorite,
color:_isFavorite ? Colors.white: Colors.red
),
onPressed: () {
setState(() {
_isFavorite= !_isFavorite;
});
box.put(1, _isFavorite);
}
)
)
)])
),
);
}
}
try:
Hive.box('your_Hive_DB_Name').containsKey(
"Key" ? Colors.red: Colors.white)
I had this test app part working. it would update bagel counter but would update all the bagel counter on screen. I moved my cubit build.provider to just the text field displaying count per item on screen.
This fix my global update to all bagel counts. so each now maintains own counter. but now when i scroll off the screen, the counts are all reset. I pull in the + 0 1 counter into listview as a class onto itself.
I have tried adding keys and
addAutomaticKeepAlives: true but no luck. fixing delete off scroll of counter 0 between + - being reset..
main.dart
//TODO Screen Layouts
//TODO json pull and post
//TODO where to send post to email sms for store to see
//TODO Update live db with fields add to test dp retailp and mobileactive
//TODO Create batch process to generate json file from db nightly or on demain via a button
//TODO TEST code
//TODO spining on load bagel icon or sprit - make.
//TODO total bagels / breads order
//TODO shopping card added
//TODO snackbar menu for as total add up pop up totals
import 'package:flutter/material.dart';
import 'Services.dart';
import 'Product.dart';
import 'bagelcounter.dart';
import 'cubit/counter_state.dart';
import 'cubit/counter_cubit.dart';
import 'cubit/counter_cubit_page.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; //addded
void main() => runApp(MyApp());
// #docregion MyApp
class MyApp extends StatelessWidget {
final bool keepAlive = true; // not working
// #docregion build
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData(
// Add the 3 lines from here...
primarySwatch: Colors.blue,
textTheme: TextTheme(
headline1: TextStyle(
fontFamily: 'Corben',
fontWeight: FontWeight.w700,
fontSize: 24,
color: Colors.black,
),
),
), // ... to here.
home: buildJsonParseDemo(),
// org home: buildJsonParseDemo(),
);
}
JsonParseDemo buildJsonParseDemo() => JsonParseDemo();
// #enddocregion build
}
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Product> _product;
bool _loading;
//quick fix make this getter
//static //todo make live counter
int mbakerdoz = 0;
//get bakerdoz => mbakerdoz;
//static //todo make live counter
int singles = 10;
#override
void initState() {
super.initState();
_loading = true;
Services.getUsers().then((product) {
setState(() {
_product = product;
_loading = false;
});
});
}
//TODO find day of week to only see items available on day:
//DateTime date = DateTime.now();
//print("weekday is ${date.weekday}");
//TODO Add quantiy field of 1 - 6 , default 0 ,to bagel and breads
//TODO Bottom total of item and price. Tax not included
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Bagels & Breads'),
),
body: Container(
color: Colors.white,
child: ListView.separated(
key: UniqueKey(),
addAutomaticKeepAlives: true, //not working to sotp skroll delete
// key: UniqueKey(), key not fix update all.
separatorBuilder: (context, index) => Divider(
color: Colors.black,
thickness: 2,
),
itemCount: null == _product ? 0 : _product.length,
itemBuilder: (context, index) {
Product product = _product[index];
return ListTile(
key: UniqueKey(),
isThreeLine: true,
// leading: Icon(Icons.plus_one),
// trailing: Icon(Icons.exposure_minus_1),
title: Text(product.pname,
style: TextStyle(
color: Colors.blue[900],
fontSize: 22.0,
fontWeight: FontWeight.w500)),
// product name
subtitle: Text(
'\$ ' +
(product.retailp.toStringAsFixed(2) +
' each index:' +
'$index ' +
' qty ' +
product.qty.toString()),
key: UniqueKey(),
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.w400)
),
trailing: SizedBox(
key: UniqueKey(),
width: 150,
child: BlocProvider<CounterCubit>(
key: UniqueKey(),
create: (context) => CounterCubit(),
child: CounterCubitPage(),
)),
);
},
),
),
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
//IconButton(icon: Icon(Icons.menu), onPressed: () {}),
Spacer(),
Container(
height: 55.0,
width: 1.0,
),
//TODO get bakerdoz and etotal on footer working need to pass data between main and bagelcounter
Text("Baker's Dozen: $mbakerdoz " + " Singles: $singles",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w500)),
Spacer(),
//IconButton(icon: Icon(Icons.search), onPressed: () {}),
//IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
],
),
shape: CircularNotchedRectangle(),
color: Colors.lightBlue,
notchMargin: 8.0,
),
//floatingActionButton:
// FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
//floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
counter_cubit_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_cubit.dart';
import 'counter_state.dart';
class CounterCubitPage extends StatelessWidget {
// static const String routeName = '/counter_cubit';
//#override
// bool get wantKeepAlive => true; // not work
// final bool keepAlive = true; // try to keep counter on skroll????
#override
Widget build(BuildContext context) => Scaffold(
key: UniqueKey(),
//appBar: AppBar(title: const Text('Counter Cubit Bloc Double CTest')),
body: BlocBuilder<CounterCubit, CounterCubitState>(
key: UniqueKey(),
builder: (context, state) => Column(
children: [
Row(
key: UniqueKey(),
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.add_circle),
color: Colors.blue,
iconSize: 25,
onPressed: () => context.read<CounterCubit>().increment(),
),
Text(
'${state.totalbagels}',
key: GlobalKey(), // not working
style: Theme.of(context).textTheme.headline4,
),
IconButton(
icon: Icon(Icons.remove_circle),
color: Colors.blue,
iconSize: 25,
onPressed: () => context.read<CounterCubit>().decrement(),
),
],
),
],
),
),
);
}
I had tried addAutomaticKeepAlives: true not working and try unique keys on fields ...
any pointers welcome. I am new to flutter coding .. still lots to learn..
enter image description here
I'm trying to use provider in my flutter app to allow the user to change the font size for some widgets.
I'm following the method described in github.com/flutter/samples/blob/master/provider_counter/lib/main.dart but the font size isn't changing.
I have a UI widget which shows plus and minus buttons:
import "package:flutter/material.dart";
import './size_controller.dart';
import 'package:provider/provider.dart';
class TypeSize extends StatelessWidget {
final _standardSize = 20.0;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(20.0),
child: Row(
children: <Widget>[
Text(
"Change type size: ",
style: TextStyle(fontSize: _standardSize),
),
ButtonTheme(
minWidth: 50,
child: RaisedButton(
onPressed: () {
if (_standardSize < 23.0) {
Provider.of<FontSizeController>(context, listen: false).increment(_standardSize);
}
},
child: Text(
"+", style: TextStyle(
color: Colors.white,
fontSize: 30),
),
color: Colors.green,
),
),
ButtonTheme(
minWidth: 50,
child: RaisedButton(
onPressed: () {
if (_standardSize > 20.0) {
Provider.of<FontSizeController>(context, listen: false).decrement(_standardSize);
}
},
child: Text(
"-", style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
color: Colors.green,
),
),
],
),
);
}
}
FontSizeController looks like this:
import 'package:flutter/material.dart';
class FontSizeController with ChangeNotifier {
double value = 20.0;
void increment(value) {
value ++;
notifyListeners();
}
void decrement(value) {
value --;
notifyListeners();
}
}
and finally the widget that I want to change looks like this:
import 'package:flutter/material.dart';
// import 'package:wfa_ambo_bloc/main.dart';
import 'package:provider/provider.dart';
import '../controllers/size_controller.dart';
class Comfort extends StatefulWidget {
#override
_ComfortState createState() => _ComfortState();
}
class _ComfortState extends State<Comfort> {
int _comfortSliderValue = 3;
// double _standardSize = 20;
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 40),
child: Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: ChangeNotifierProvider(
create: (context) => FontSizeController(),
child: Container(
padding: EdgeInsets.all(20.0),
child: Consumer<FontSizeController>(
builder: (
context,
sizeController,
child) => Text(
"How comfortable was your journey?",
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w400,
fontFamily: "Roboto",
letterSpacing: 0.5,
fontSize: sizeController.value,
),
),
),
),
),
),
... etc
Nothing is happening when the buttons are clicked. Can anybody help please?
The example that I'm trying to adapt is all contained within the main() but I've separated out my widgets to try and make everything cleaner - is that what is making the difference?
No need to use a variable in your widget (remove _standardSize).
Just keep the value in your ChangeNotifier and use it directly (through a getter) :
import 'package:flutter/material.dart';
class FontSizeController with ChangeNotifier {
double _value = 20.0;
int get value => _value;
void increment() {
_value++;
notifyListeners();
}
void decrement() {
_value--;
notifyListeners();
}
}
Then on plus and minus buttons, simply increment or decrement value from your ChangeNotifier :
// on plus button pressed
Provider.of<FontSizeController>(context, listen: false).increment();
// on minus button pressed
Provider.of<FontSizeController>(context, listen: false).decrement();
Finally in the widget where you want your text to be sized :
fontSize: Provider.of<FontSizeController>(context, listen: true).value