I'm new and I'm writing the settings section of my app in Flutter (I'm using this package: https://pub.dev/packages/flutter_settings_screens).
I get this error "setState() or markNeedsBuild() called during build." when the value of my TextInputSettingsTile changes.
I read a lot of information on the net but I still don't understand what is the problem.
This is my main.dart:
import 'package:flutter/material.dart';
import 'pages/home.dart';
import 'pages/settings_page.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
Future main() async {
await Settings.init(cacheProvider: SharePreferenceCache());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LoginPage(title: 'TEST'),
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<LoginPage> createState() => LoginPageState();
}
class LoginPageState extends State<LoginPage> {
final _username = TextEditingController();
final _password = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SettingsPage()),
);
},
icon: const Icon(Icons.settings))
],
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(
20, 0, 20, 10),
child: TextField(
controller: _username,
decoration: InputDecoration(
icon: const Icon(Icons.email),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
),
labelText: 'username'),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(
20, 5, 20, 10),
child: TextField(
controller: _password,
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
icon: const Icon(Icons.password_rounded),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
),
labelText: 'password'),
)),
ElevatedButton(
onPressed: () => {},
child: const Text('LOGIN'))
],
),
),
);
}
}
This is my settings general page:
import 'package:flutter/material.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import 'settings/connection_page.dart';
class SettingsPage extends StatefulWidget {
#override
SettingsPageState createState() => SettingsPageState();
}
class SettingsPageState extends State<SettingsPage> {
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Settings')
),
body: SafeArea(
child: ListView(
padding: const EdgeInsets.all(12),
children: [
const SizedBox(height: 5,),
SettingsGroup(
title: 'GENERAL', children: const <Widget>[
ConnectionPage()
]
),
],
),
),
);
}
This is my settings specific page (where I'm getting the error):
import 'package:flutter/material.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class ConnectionPage extends StatelessWidget {
const ConnectionPage({Key? key}) : super(key: key);
static const keyServer = 'key-server';
#override
Widget build(BuildContext context) => SimpleSettingsTile(
title: 'Connection',
subtitle: 'Parameters',
leading: const FaIcon(FontAwesomeIcons.clipboardList),
child: SettingsScreen(
title: 'Connection',
children: <Widget>[
buildServer(),
],
),
);
Widget buildServer() => TextInputSettingsTile(
settingKey: keyServer,
title: 'Server',
initialValue: ''
);
}
What can I do in order to fix this error?
Thank you all.
Some method underneath it is calling a setState during a build. Identify it and use the addPostFrameCallback method.
Example:
import 'package:flutter/material.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import 'settings/connection_page.dart';
class SettingsPage extends StatefulWidget {
#override
SettingsPageState createState() => SettingsPageState();
}
class SettingsPageState extends State<SettingsPage> {
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Settings')
),
body: SafeArea(
child: ListView(
padding: const EdgeInsets.all(12),
children: [
const SizedBox(height: 5,),
WidgetsBinding.instance.addPostFrameCallback((_){
SettingsGroup(
title: 'GENERAL', children: const <Widget>[
ConnectionPage()
]),
});
],
),
),
);
}
Try verify as ths example. Try wrapping it into WidgetsBinding.instance.addPostFrameCallback((_)
Related
I have a DropdownButton in my custom header widget that doesn't work. If I put the button in the content of the program it works fine, but not in the header. I get no errors.
This is the widget:
import 'package:flutter/material.dart';
class TestBar extends StatelessWidget {
const TestBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
height: 80.0,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: const [
Text('Text', style: TextStyle(fontSize: 18.0),),
SizedBox(width: 20.0,),
DropTest(
items: [
'Collections',
'Item 1',
'Item 2',
'Item 3',
],
),
SizedBox(width: 20.0,),
Text('Text', style: TextStyle(fontSize: 18.0),),
SizedBox(width: 20.0,),
],
),
);
}
}
class DropTest extends StatelessWidget {
final List<String> items;
const DropTest({Key? key, required this.items}) : super(key: key);
#override
Widget build(BuildContext context) {
return DropdownButton(
value: items[0],
elevation: 0,
style: const TextStyle(fontSize: 18.0),
icon: const Icon(Icons.keyboard_arrow_down_outlined, size: 20,),
underline: Container(height: 0,),
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 18.0),
),
);
}).toList(),
onChanged: (String? newValue) {
switch (newValue) {
case 'Cucine':
return _goToPath(cucineRoute);
case 'Bagni':
return _goToPath(bagniRoute);
case 'Living':
return _goToPath(livingRoute);
default:
return;
}
},
);
}
}
void _goToPath(String navigationPath) {
//navigation to a certain page;
}
And this is where I use the header widget:
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:sito_woodandstone/settings/constants.dart';
import 'package:sito_woodandstone/widgets/navigation_bar/test_bar.dart';
class LayoutTemplate extends StatelessWidget {
final Widget child;
const LayoutTemplate({Key? key, required this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
return ResponsiveBuilder(
builder: (context, sizingInformation) => Scaffold(
backgroundColor: colorBackground,
body: Column(
children: [
const TestBar(),
//NavBar(),
Expanded(
child: child,
),
],
),
),
);
}
}
This is where the LayoutTemplate is used in the main function
import 'package:flutter/material.dart';
import 'package:sito_woodandstone/locator.dart';
import 'package:sito_woodandstone/routing/rout_names.dart';
import 'package:sito_woodandstone/routing/router.dart';
import 'package:sito_woodandstone/services/navigation_serivice.dart';
import 'package:sito_woodandstone/views/layout_template/layout_template.dart';
void main() {
setupLocator();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Wood & Stone',
theme: ThemeData(
textTheme:
Theme.of(context).textTheme.apply(fontFamily: 'HeadingPro')),
builder: (context, child) => LayoutTemplate(child: child!),
navigatorKey: locator<NavigationService>().navigatorKey,
onGenerateRoute: generateRoute,
initialRoute: cucineRoute,
);
}
}
The Dropdown button below in the content is working but the one above is not image
I tried to remove the responsive builder but that is not the problem. I think there is something off in the main function, but I can't figure out what it is... Any ideas? Please help
So we have a Dismissible for confirming/denying a item.
However we have some users that are trying to click/tap on the item.
Our UX team suggested that we then "bounce" the item to show that they have to swipe (and reveal the action fields).
But I don't see any option to do so.
Does anybody have a suggestion what might work for this?
The code I have for now is shown below:
Dismissible(
key: const ValueKey(0),
direction: DismissDirection.horizontal,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 3, vertical: 3),
child: card(),
),
confirmDismiss: (direction) async {
var newStatus = direction == DismissDirection.startToEnd
? OkNokNvt.OK
: OkNokNvt.NOK;
_changeStatus(newStatus);
return false;
},
background: ok(),
secondaryBackground: nok(),
),
The Dismissable doesn't seeem to have this functionality.
Instead, you could use the flutter_slidable package.
Here, you can programmatically open the underlying actions by calling Slideable.of(context)?.open(). No fancy bounce-animation though.
Here's the code:
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Slidable(
key: const Key('key'),
actionPane: const SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Builder(
builder: (context) => GestureDetector(
onTap: () {
Slidable.of(context)
?.open(actionType: SlideActionType.primary);
},
child: Container(
color: Colors.grey,
height: 50,
child: const Center(child: Text('Tap me')),
),
),
),
actions: [
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => print('remove me from list'),
),
],
dismissal: SlidableDismissal(
onDismissed: (_) => print('remove me from list'),
dragDismissible: true,
child: const SlidableDrawerDismissal(),
),
),
],
),
),
);
}
}
Here is my minimal example which does what you are looking for.
Basically, the GestureDetector onTap callback triggers the animation which has a bouncing-like effect by using a sin function on the _animation.value. The behaviour can be tweeked by changing the parameters cyclesPerAnimation and bounceOffset.
Simply put your Dismissible in the place of the Container and you should be good to go.
environment:
sdk: ">=2.12.0 <3.0.0"
import 'dart:math';
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 MaterialApp(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late final AnimationController _animation = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
Offset _bounceOffset(double animationValue) {
const cyclesPerAnimation = 2;
const bounceOffset = 10;
return Offset(
0,
sin(animationValue * pi * 2 * cyclesPerAnimation) * bounceOffset,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedBuilder(
animation: _animation,
builder: (context, widget) => Transform.translate(
offset: _bounceOffset(_animation.value),
child: GestureDetector(
onTap: () {
_animation.reset();
_animation.forward();
},
child: Container(
color: Colors.grey,
height: 50,
width: 200,
child: const Center(child: Text('Tap to bounce')),
),
),
),
),
],
),
),
);
}
}
I am trying to convert TextEditingController into int because I want to delete the user ID from database by using TextEditingController.
look at: (<-------) in the code to understand.
and here is my code:
import 'package:flutter/material.dart';
import 'package:untitled/database.dart';
import './model/columns.dart';
import './database.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void dispose() {
textController.dispose();
super.dispose();
}
final textController = TextEditingController();
int? selectedId;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("App"),
),
body: Form(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: textController,
decoration: InputDecoration(
labelText: "Insert row",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25))),
),
),
ElevatedButton(
child: Icon(Icons.save),
onPressed: () async {
await DatabaseHelper.instance
.insert(Users(name: textController.text));
setState(() {
textController.clear();
});
print("Inserted!");
},
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: selectedId, // <-------
decoration: InputDecoration(
labelText: "Delete ID",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25))),
keyboardType: TextInputType.number,
),
),
ElevatedButton(
child: Icon(Icons.delete),
onPressed: () async {
DatabaseHelper.instance.delete(selectedId!); // <-------
},
),
ElevatedButton(
child: Text("Check all rows"),
onPressed: () async {
print(await DatabaseHelper.instance.queryAll());
},
),
],
),
)),
);
}
}
Create another controller then pass as the entered data as int by converting with int.parse(yourcontroller.text)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final textController = TextEditingController();
final numberController = TextEditingController();
#override
void dispose() {
textController.dispose();
numberController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: numberController,
decoration: InputDecoration(
labelText: "Delete ID",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25))),
keyboardType: TextInputType.number,
),
),
ElevatedButton(
child: Icon(Icons.delete),
onPressed: () async {
DatabaseHelper.instance.delete(int.parse(numberController.text));
print(int.parse(numberController.text));
},
),
],
),
),
);
}
}
I am working on a custom dialog called "Alertbox" where the user inserts a name into a textfield and after he pushes the button a function called "addTeam" created a team out of the string.
This is how I created my dialog "Alertbox":
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:trainings_app/config/palette.dart';
class Alertbox extends StatelessWidget {
final Function addTeamFunction;
const Alertbox(this.addTeamFunction);
#override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: EdgeInsets.all(10),
child: Center(
child: Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(const Radius.circular(20)),
color: Colors.white,
),
width: 350,
height: 200,
child: Row(
children: [
SizedBox(width: 12),
Expanded(
child: TextField(
textAlign: TextAlign.center,
autofocus: true,
),
),
SizedBox(width: 12),
ElevatedButton(
onPressed: () => addTeamFunction(),
child: const Text('✓'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Palette.orange),
),
),
SizedBox(width: 8),
],
),
),
),
);
}
}
And here I am using it:
void newTeam() {
showDialog<AlertDialog>(
context: context,
builder: (BuildContext context) {
return Alertbox(() {
Navigator.of(context).pop();
});
},
);
}
void addTeam(String name) {
setState(() {
teams.add(name);
});
Navigator.of(context).pop();
sharedPreferences.setStringList('teams', teams);
}
But I can't find a way to parse the input from the textfield into the function "addTeam" where it is needed. Can anyone help me please?
You Should try below code hope its helps you:
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 const MaterialApp(
title: 'Testing',
home: MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(myController.text),
);
},
);
},
tooltip: 'Show the value!',
child: const Icon(Icons.add),
),
);
}
}
Your Screen like ->
Use a TextFormField instead of a TexiField widget contained in a Form widget that has a GlobalKey, which will be useful to you during validation!
How to get the value which is already entered on the keyboard?
Uses a TextEditingController or the onSaved method of the TextFormField.
I'm making a flutter project
I want to merge a lot of widgets that I made.
but I can't merge......
if I try to merge it occurred error.
How can i solve this?
I have no idea.....
please let me know.
this is my code
******* here are codes in Column ***********
1.lendproductlist -> it is actually just listview example
2.search bar -> it is searchbar layout
3. appbar
import 'package:flutter/material.dart';
void main() => runApp(LendProductList());
/// This is the main application widget.
class LendProductList extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: null,
body: MyStatelessWidget(),
),
);
}
}
class CustomListItem extends StatelessWidget {
const CustomListItem({
this.thumbnail,
this.title,
this.user,
this.viewCount,
});
final Widget thumbnail;
final String title;
final String user;
final int viewCount;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 2,
child: thumbnail,
),
Expanded(
flex: 3,
child: _VideoDescription(
title: title,
user: user,
viewCount: viewCount,
),
),
const Icon(
Icons.more_vert,
size: 16.0,
),
],
),
);
}
}
class _VideoDescription extends StatelessWidget {
const _VideoDescription({
Key key,
this.title,
this.user,
this.viewCount,
}) : super(key: key);
final String title;
final String user;
final int viewCount;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14.0,
),
),
const Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text(
user,
style: const TextStyle(fontSize: 10.0),
),
const Padding(padding: EdgeInsets.symmetric(vertical: 1.0)),
Text(
'$viewCount views',
style: const TextStyle(fontSize: 10.0),
),
],
),
);
}
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 400,
child: ListView(
padding: const EdgeInsets.all(8.0),
itemExtent: 106.0,
children: <CustomListItem>[
CustomListItem(
user: 'Flutter',
viewCount: 999000,
thumbnail: Container(
decoration: const BoxDecoration(color: Colors.blue),
),
title: 'The Flutter YouTube Channel',
),
CustomListItem(
user: 'Dash',
viewCount: 884000,
thumbnail: Container(
decoration: const BoxDecoration(color: Colors.yellow),
),
title: 'Announcing Flutter 1.0',
),
],
),
);
}
}
import 'package:flutter/material.dart';
void main() => runApp(SearchbarApp());
class SearchbarApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title:'searchbar',
home: SearchbarScreen(),
);
}
}
class SearchbarScreen extends StatefulWidget {
#override
_SearchbarScreenState createState() => _SearchbarScreenState();
}
class _SearchbarScreenState extends State<SearchbarScreen> {
final TextEditingController _textController = new TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: null,
body: _buildTextComposer(),
),
);
}
Widget _buildTextComposer() {
return IconTheme(
data: IconThemeData(color: Theme
.of(context)
.accentColor),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: <Widget>[
Container(
width: 280,
child: TextField(
controller: _textController,
onSubmitted: _handleSubmitted,
decoration: new InputDecoration.collapsed(
hintText: "검색어를 입력하세요."),
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: Icon(Icons.search),
onPressed: () => _handleSubmitted(_textController.text)),
),
],
),
)
);
}
void _handleSubmitted(String text) {
_textController.clear();
} }
import 'package:flutter/material.dart';
void main() => runApp(BillrunAppbar());
class BillrunAppbar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home:Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text("BULL RUN",style: TextStyle(fontSize: 30.0, fontWeight : FontWeight.bold,color:Colors.black),
),
),
)
);
}
}
You need to create one class for Application and place exists widgets to it:
Create only one App class;
In App class declare AppBar;
Remove from widgets Material app, for example:
class LendProductList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MyStatelessWidget()
}
}
If you are using constant widget sizes and you have many widgets on the screen, wrap parent of its to ListView or SingleChildScrollView.