What we should do when the file gets so long - flutter

when I'm done with a page I can extract widget as I can for more readable, But this makes the file longer, So I find a solution I can use "part and part of " I can take extract widgets inside part of (E.g login_view_part.dart), this solves the problem, But I have read opinions about the non-use/bad-use of part and part of.
1- this is a good solution for problems like this? If not what should we
do?
2- we should use part and part of? anywhere. (except code generation)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:second_hand/core/constants/navigation/navigation_constants.dart';
import 'package:second_hand/core/extensions/context_extension.dart';
import 'package:second_hand/core/init/navigation/navigation_service.dart';
import 'package:second_hand/core/init/notifier/product_notifer.dart';
import 'package:second_hand/view/_product/_widgets/textformfield/custom_text_form_field.dart';
import 'package:second_hand/view/app/addproduct/include_some_details/viewmodel/include_some_details_view_model.dart';
enum ProductState {
verybad(name: 'Very Bad'),
bad(name: 'Bad'),
normal(name: 'Normal'),
good(name: 'Good'),
verygood(name: 'Very Good');
const ProductState({required this.name});
final String name;
}
class IncludeSomeDetailsView extends StatefulWidget {
const IncludeSomeDetailsView({super.key});
#override
State<IncludeSomeDetailsView> createState() => IncludeSomeDetailsViewState();
}
class IncludeSomeDetailsViewState extends IncludeSomeDetailsViewModel {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Include some details'),
),
body: Form(
key: formKey,
child: Padding(
padding: context.paddingAllMedium,
child: Column(
children: [
TitleTextFormField(titleController: titleController),
DescriptionTextFormField(describeController: describeController),
DropdownButton<ProductState>(
value: valueProductState,
items: ProductState.values
.map<DropdownMenuItem<ProductState>>(
(value) => DropdownMenuItem<ProductState>(
value: value,
child: Text(value.name),
),
)
.toList(),
onChanged: (productState) {
setState(
() {
stateController.text = productState!.name;
valueProductState = productState;
},
);
},
),
const Spacer(),
NextButton(
formKey: formKey,
titleController: titleController,
stateController: stateController,
describeController: describeController),
],
),
),
),
);
}
}
class TitleTextFormField extends StatelessWidget {
const TitleTextFormField({
Key? key,
required this.titleController,
}) : super(key: key);
final TextEditingController titleController;
#override
Widget build(BuildContext context) {
return Padding(
padding: context.paddingOnlyTopSmall,
child: CustomTextFormField(
controller: titleController,
labelText: 'title',
prefix: const Icon(Icons.title_outlined),
),
);
}
}
class DescriptionTextFormField extends StatelessWidget {
const DescriptionTextFormField({
Key? key,
required this.describeController,
}) : super(key: key);
final TextEditingController describeController;
#override
Widget build(BuildContext context) {
return Padding(
padding: context.paddingOnlyTopSmall,
child: CustomTextFormField(
controller: describeController,
labelText: 'description',
prefix: const Icon(Icons.description),
),
);
}
}
class NextButton extends StatelessWidget {
const NextButton({
Key? key,
required this.formKey,
required this.titleController,
required this.stateController,
required this.describeController,
}) : super(key: key);
final GlobalKey<FormState> formKey;
final TextEditingController titleController;
final TextEditingController stateController;
final TextEditingController describeController;
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
context.read<ProductNotifier>().setProduct(
title: titleController.text,
state: stateController.text,
description: describeController.text,
);
NavigationService.instance.navigateToPage(path: NavigationConstants.UPLOAD_PHOTOS);
}
},
child: const Text(
'Next',
),
);
}
}

Related

How to create type of textfield / textbox it shouldn't be a single widget

How to create type of Text field? it shouldn't be a single widget. is there any way to create like this?
this might help.textformfield
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: 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({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
#override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Shortcuts(
shortcuts: const <ShortcutActivator, Intent>{
// Pressing space in the field will now move to the next field.
SingleActivator(LogicalKeyboardKey.space): NextFocusIntent(),
},
child: FocusTraversalGroup(
child: Form(
autovalidateMode: AutovalidateMode.always,
onChanged: () {
Form.of(primaryFocus!.context!)!.save();
},
child: Wrap(
children: List<Widget>.generate(5, (int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ConstrainedBox(
constraints: BoxConstraints.tight(const Size(200, 50)),
child: TextFormField(
onSaved: (String? value) {
debugPrint(
'Value for field $index saved as "$value"');
},
),
),
);
}),
),
),
),
),
),
);
}
}

Why is the refreshing pull in the App not working?

I'm building my app with Flutter 2.10.5 and Dart 2.16.2.
When i try to refresh the demo content whith a pull, nothing happens. I have multiple navigation routes for different content. So the demo is a litte bit complex.
The main.dart includes the basic code for the app. I use the NavDrawer Widget to build the different pages. Every route is defined in the navigation.dart file, which reference to the content widgets.
My code so far is:
import 'dart:core';
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of the application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo Company',
theme: ThemeData(),
debugShowCheckedModeBanner: false,
home: const HomePage(title: 'Demo Company'),
);
}
}
class _HomePageState extends State<HomePage> {
#override
initState() {
super.initState();
}
Widget _infoTile(String title, String subtitle) {
return ListTile(
title: Text(title),
subtitle: Text(subtitle.isEmpty ? 'Not set' : subtitle),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: const NavDrawer(),
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
_infoTile('App name', 'Demo App....'),
// Multiple Liste Tiles...
],
),
),
);
}
}
//----------------------------------------------------------------------
// navigation.dart
//----------------------------------------------------------------------
class NavDrawer extends StatelessWidget {
const NavDrawer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text(
'Navigation',
style: TextStyle(color: Colors.white, fontSize: 30),
),
SizedBox(height: 30.0),
Text('Firstname', style: TextStyle(color: Colors.black, fontSize: 15)),
Text('Accountname', style: TextStyle(color: Colors.black, fontSize: 15)),
],
),
),
ListTile(
leading: const Icon(Icons.notifications),
title: const Text('Demo'),
onTap: () {
Navigator.push(
context,
Demo.route(),
);
},
),
// Multiple Navigation List Tiles...
],
),
);
}
}
//----------------------------------------------------------------------
// demo.dart
//----------------------------------------------------------------------
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<HomePage> createState() => _HomePageState();
}
class Demo extends StatefulWidget {
const Demo({Key? key}) : super(key: key);
static Route route() {
return CupertinoPageRoute(builder: (_) => const Demo());
}
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
final _data = <WordPair>[];
#override
void initState() {
super.initState();
_data.addAll(generateWordPairs().take(20));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
),
body: _buildList(),
);
}
Widget _buildList() {
return RefreshIndicator(
onRefresh: _refreshData,
child: ListView.builder(
padding: const EdgeInsets.all(20.0),
itemBuilder: (context, index) {
WordPair wordPair = _data[index];
return _buildListItem(wordPair.asString, context);
},
itemCount: _data.length,
),
);
}
Widget _buildListItem(String word, BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(word),
),
);
}
Future _refreshData() async {
await Future.delayed(const Duration(seconds: 3));
_data.clear();
_data.addAll(generateWordPairs().take(20));
setState(() {});
}
}
class ShowMessages extends StatelessWidget {
final String type;
final Color color;
const ShowMessages({Key? key, required this.type, required this.color}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView(
//color: color,
physics: const AlwaysScrollableScrollPhysics(),
children: [
ListTile(
title: Text(
type,
style: Theme.of(context).textTheme.bodyText1,
),
),
]);
}
}
Copy this code to DartPad
What is wrong?
Well for me this code... works
I copied it into Dartpad, then Dev Tools in browser (F12) > Device Emulation > Responsive. And you can use pull to refresh.
Of course this doesn't work using web view and mouse. I believe this gesture is not supported.

How to update screen when instance of external stateful widget class is updated

I am displaying the weight of an instance of a person class on my homepage. When I update the weight of this instance through a form in a popup bottom sheet the displayed weight is only changed after a hot reload. How can I trigger a setState in my person class when its instances parameters are changed in homepage?
main.dart
import 'package:flutter/material.dart';
import 'package:metricwidget/screens/homepage.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// Root of application
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Homepage(),
);
}
}
person.dart
import 'package:flutter/material.dart';
class person extends StatefulWidget {
int? weight;
person({Key? key, this.weight}) : super(key: key);
void updateWeight(newWeight){
weight = newWeight;
}
#override
_personState createState() => _personState();
}
class _personState extends State<person> {
#override
Widget build(BuildContext context) {
return Center(
child: Text(
widget.weight.toString(),
style: const TextStyle(fontSize: 24),
),
);
}
}
homepage.dart
import 'package:mvs/person.dart';
import 'package:flutter/material.dart';
class Homepage extends StatefulWidget {
const Homepage({Key? key}) : super(key: key);
#override
_HomepageState createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
var joe = person(weight: 23);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Material(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: joe,
),
OutlinedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return Form(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
onSaved: (String? value) {
if (int.parse(value!) > 0) {
setState(() {
joe.updateWeight(int.parse(value));
});
}
},
keyboardType: TextInputType.number,
maxLength: 3,
initialValue: joe.weight.toString(),
decoration: const InputDecoration(
icon: Icon(Icons.label),
),
validator: (value) {
if (value!.isEmpty) {
return "Please enter value";
}
return null;
},
),
),
OutlinedButton(
onPressed: () {
_formKey.currentState!.save();
Navigator.pop(context);
},
child: const Text("submit"),
)
],
),
);
},
);
},
child: const Text("Update"),
)
],
),
);
}
}
Was able to solve this using provider and changenotifier, same as the format outlined in the docs below
Reference: https://pub.dev/packages/provider

Cannot retrieve text from textfield with Riverpod

My code
class _GenericTextFieldState extends State<GenericTextField> {
#override
Widget build(BuildContext context) {
return CupertinoTextField(
controller: textFieldController,
padding: EdgeInsets.all(8),
prefix: Icon(Icons.email_outlined),
placeholder: widget.hint,
);
}
}
final textFieldController = TextEditingController();
final textFieldProvider = Provider<String> ( (_) => textFieldController.text);
the textFieldController is supplying the string to the textFieldProvider.
I am trying to get the string in another file using the consumer widget like so
class LoadingButton extends ConsumerWidget {
LoadingButton(this.buttonName);
final String buttonName;
#override
Widget build(BuildContext context,ScopedReader watch) {
String textInput = watch(textFieldProvider);
return RoundedLoadingButton(
successColor: mainColor,
errorColor: Colors.orange,
height: 40,
color: mainColor,
child: Text(buttonName, style: TextStyle(color: Colors.white)),
controller: _btnController,
onPressed: (){
mLog("Input from provider username: $textInput");
},
);
}
}
However the textInput variable is always empty.
What am I missing.
you can use onChanged with StateProvider
something like this
Full Example
final textFieldProvider = StateProvider<String>((ref) => "");
class Main extends StatelessWidget {
const Main({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ProviderScope(
child: Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: Column(
children: [
Container(),
_GenericTextFieldState(),
LoadingButton("Test")
],
),
),
);
}
}
class _GenericTextFieldState extends StatelessWidget {
const _GenericTextFieldState({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return CupertinoTextField(
padding: EdgeInsets.all(8),
prefix: Icon(Icons.email_outlined),
placeholder: "Input text",
onChanged: (text) {
context.read(textFieldProvider).state = text;
},
);
}
}
class LoadingButton extends ConsumerWidget {
LoadingButton(this.buttonName);
final String buttonName;
#override
Widget build(BuildContext context, ScopedReader watch) {
String textInput = watch(textFieldProvider).state;
return RaisedButton(
child: Text(buttonName, style: TextStyle(color: Colors.white)),
onPressed: () {
print("Input from provider username: $textInput");
},
);
}
}

How do I extract this switch widget

I have a StatefulWidget with a ListView, the ListView has the bunch of switches with text next to them.
Now i want to extract this into a custom switch widget because i have this more than once.
I don't know how to do this, also I need to know inside my parent widget what state each switch has.
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Use custom dhcp server"),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Switch(
value: _dhcp,
activeColor: Colors.blue,
onChanged: (bool value) {
setState(() {
_dhcp = value;
});
},
),
),
],
),
),
You can create your own stateless widget like this:
class CustomSwitch extends StatelessWidget {
const CustomSwitch({
Key key,
#required this.value,
#required this.onChanged,
}) : super(key: key);
final bool value;
final void Function(bool) onChanged;
#override
Widget build(BuildContext context) {
return Switch(
value: value,
activeColor: Colors.blue,
onChanged: onChanged,
);
}
}
Where you can use it anywhere like this:
class ParentWidget extends StatefulWidget {
#override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
bool switchValue = false;
#override
Widget build(BuildContext context) {
return ListView(
children: [
CustomSwitch(
value: switchValue,
onChanged: (newValue) {
setState(() {
switchValue = newValue;
});
},
),
],
);
}
}