How to modify the value of another TextFieldBlocBuilder programmatically? - android-studio

I have the following classes:
AddFormBloc
class AddFormBloc extends FormBloc<String,String>{
// ignore: close_sinks
final trackField = TextFieldBloc(
asyncValidatorDebounceTime: Duration(milliseconds: 500),
);
final latField = TextFieldBloc();
final longField = TextFieldBloc();
AddFormBloc(){
trackField.addAsyncValidators([_isValidTrack]);
addFieldBlocs(fieldBlocs: [
trackField,
latField,
longField
]);
}
...
#override
Stream<FormBlocState<String, String>> onSubmitting() async* {
try{
print(trackField.value);
await Future<void>.delayed(Duration(seconds:2));
yield state.toSuccess();
}catch(e){
yield state.toFailure(
failureResponse: 'Fake error, please continue testing the async validation.'
);
}
}
}
FormAddSong
class FormAddSong extends StatefulWidget {
#override
_FormAddSongState createState() => _FormAddSongState();
}
class _FormAddSongState extends State<FormAddSong> {
AddFormBloc _addFormBloc;
Completer<GoogleMapController> _controller = Completer();
double _lat; //latitud
double _lng; //longitud
Set<Marker> _markers = Set();
#override
void initState() {
super.initState();
_addFormBloc = AddFormBloc();
}
#override
void dispose() {
_addFormBloc.delete();
super.dispose();
}
#override
Widget build(BuildContext context) {
String pattern = "https://open.spotify.com/track/";
String patternIdTrack="4QupQwSViJ7sdZWZOkzZV5";
return Container(
child: FormBlocListener(
formBloc: _addFormBloc,
onSubmitting: (context, state){
showDialog(
context: context,
barrierDismissible: false,
builder: (_) => WillPopScope(
onWillPop: () async => false,
child: Center(
child: Card(
child: Container(
width: 80,
height: 80,
padding: EdgeInsets.all(12.0),
child: CircularProgressIndicator(),
),
),
),
),
);
},
onSuccess: (context, state){
Navigator.of(context).pop();
showDialog(context: context, builder: (_) => AlertDialog(
title: Text("se ha agregado correctamente"),
));
},
onFailure: (context, state){
// Hide the progress dialog
Navigator.of(context).pop();
// Show snackbar with the error
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(state.failureResponse),
backgroundColor: Colors.red[300],
),
);
},
child: Column(
children: [
TextFieldBlocBuilder(
maxLength: patternIdTrack.length+pattern.length,
textFieldBloc: _addFormBloc.trackField,
decoration: InputDecoration(
labelText: 'Enlace canción en Spotify',
hintText: 'Enlace canción en Spotify',
prefixIcon: Icon(Icons.music_note),
suffixIcon: IconButton(
icon: Icon(Icons.info_outline),
onPressed: (){
Navigator.push(context,
MaterialPageRoute(builder: (context) => OnBoardingGuideSpotifyLinkPage()));
},
),
),
),
TextFieldBlocBuilder(
isEnabled: false,
textFieldBloc: _addFormBloc.latField,
decoration: InputDecoration(
labelText: 'Latitud (Clic mapa)',
hintText: 'Latitud (Clic mapa)',
prefixIcon: Icon(Icons.edit_location)
),
),
TextFieldBlocBuilder(
readOnly: true,
textFieldBloc: _addFormBloc.longField,
decoration: InputDecoration(
labelText: 'Longitud (Clic mapa)',
hintText: 'Longitud (Clic mapa)',
prefixIcon: Icon(Icons.edit_location)
),
),
SizedBox(height: MediaQuery.of(context).devicePixelRatio*10.0),
FutureBuilder(
future: _initialCameraP(),
builder: (BuildContext context, AsyncSnapshot<Tuple2<Position,Uint8List>>snapshot){
if(snapshot.hasData){
Position ps = snapshot.data.item1;
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(ps.latitude,ps.longitude),
zoom: (ps.latitude==0.0 && ps.longitude == 0.0)?2.0:10.0
),
markers: _markers,
onMapCreated: (GoogleMapController controller){
_lat = ps.latitude;
_lng = ps.longitude;
_controller.complete(controller);
},
onTap: (LatLng latLng){
setState(() {
_markers.clear(); //limpiar lista para que solo aparezca sobre donde hemos clicado
//añadir donde hemos clicado
_markers.add(Marker(
markerId: MarkerId(latLng.toString()),
icon: BitmapDescriptor.fromBytes(snapshot.data.item2),
position: latLng,
));
});
},
);
}else{
return CircularProgressIndicator();
}
},
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: _addFormBloc.submit,
child: Center(child: Text('Enviar')),
),
),
],
),
),
);
}
What I am trying to do is that when a user tap on the GoogleMap, I automatically save the latitude and longitude in some variables and insert those values in the corresponding latitude and longitude textfieldblocbuilder.
Without Bloc, I know how to do it in normal forms, but with Bloc I can't find the way.

Related

Flutter; List obs does not refresh new elements on default tab controller tabs

Hello i am learning the state using the getX methods. When the app loads i am adding the categories in the list but the issue is not updating. can anybody look whats my wrong?
Restaurant Ui Button Page:
HomeController con = Get.put(HomeController());
Widget _cardRestoran(BuildContext context, Restaurants restaurant) {
return GestureDetector(
onTap: () {
con.restoranProducts(context, restaurant);
},
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 15, left: 20, right: 20),
child: ListTile(
title: Text('${restaurant.name ?? ''}' ,),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 5),
Text(
' Şehir: ${restaurant.il ?? ''} - İlçe: ${restaurant.ilce ?? ''}' ,
maxLines: 2,
style: TextStyle(
fontSize: 13
),
),
SizedBox(height: 15),
],
),
trailing: Container(
height: 70,
width: 60,
// padding: EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: FadeInImage(
image: restaurant.image != null
? NetworkImage(restaurant.image ?? '')
: AssetImage('assets/img/no-image.png') as ImageProvider,
fit: BoxFit.cover,
fadeInDuration: Duration(milliseconds: 50),
placeholder: AssetImage('assets/img/no-image.png'),
),
),
),
),
),
Divider(height: 1, color: Colors.grey[300], indent: 37, endIndent: 37,)
],
),
);
}
Home Controller
class HomeController extends GetxController{
void restoranProducts(BuildContext context, Restaurants restaurants) async{
await showMaterialModalBottomSheet(
context: context,
useRootNavigator: true,
builder: (context) => RestoranProducts(restaurants: restaurants),
);
}
}
Restaurant Category Controller :
class ClientRestoranProductListController extends GetxController{
String res_id;
List<Category> categories = <Category>[].obs;
ClientRestoranProductListController(#required this.res_id){
getCategories();
}
void getCategories() async {
var result = await categoriesProvider.restaurantCategory("${this.res_id}");
categories.clear();
categories.addAll(result);
}
}
I also tried seperate but it still didnt work.
Restoran Products Category List UI page:
class RestoranProducts extends StatefulWidget {
final Restaurants? restaurants;
const RestoranProducts({Key? key, required this.restaurants}) : super(key: key);
#override
State<RestoranProducts> createState() => _RestoranProductsState();
}
class _RestoranProductsState extends State<RestoranProducts> {
Widget build(BuildContext context) {
String restoranSahibi = "${widget.restaurants?.user_id}";
ClientRestoranProductListController con = Get.put(ClientRestoranProductListController(restoranSahibi));
return Obx(() => DefaultTabController(
length: con.categories.length,
child: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => setState((){
})),
drawer: HomeNavigator(),
appBar: PreferredSize(
preferredSize: Size.fromHeight(110),
child:AppBar(
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors:
[
Colors.amber,
Colors.black,
],
begin: FractionalOffset(0.0, 0.0),
end: FractionalOffset(1.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp,
)
),
margin: EdgeInsets.only(top: 15),
alignment: Alignment.topCenter,
child: Wrap(
direction: Axis.horizontal,
children: [
_textFieldSearch(context),
_iconShoppingBag()
],
),
),
centerTitle: true,
iconTheme: IconThemeData(color: Colors.white),
bottom: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
labelColor: Colors.black,
unselectedLabelColor: Colors.white,
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
color: Colors.white
),
tabs: List<Widget>.generate(con.categories.length, (index) {
return Tab(
child: Text(con.categories[index].name ?? ''),
);
}),
),
) ,
),
body: TabBarView(
key: Key(Random().nextDouble().toString()),
children: con.categories.map((Category category) {
return FutureBuilder(
future: con.getProducts(category.id ?? '1', con.productName.value),
builder: (context, AsyncSnapshot<List<Product>> snapshot) {
if (snapshot.hasData) {
if (snapshot.data!.length > 0) {
return ListView.builder(
itemCount: snapshot.data?.length ?? 0,
itemBuilder: (_, index) {
return _cardProduct(context, snapshot.data![index]);
}
);
}
else {
return NoDataWidget(text: 'No category');
}
}
else {
return NoDataWidget(text: 'No category');
}
}
);
}).toList(),
)
),
));
}
}
i tried seperate ways but it did not work.

The argument type 'String' can't be assigned to the parameter type 'AllPosts'

I'm not sure why it can't saveform. Please help me QAQ this is messing up my life
This is the error:
lib/navpages/upload/edit_post_screen.dart:98:65: Error: The argument type 'String' can't be assigned to the parameter type 'AllPosts'.
'AllPosts' is from 'package:pinsta/providers/all_posts.dart' ('lib/providers/all_posts.dart').
onPressed:() => saveForm(i,caption!),
^
import 'package:flutter/material.dart';
import 'package:pinsta/models/post.dart';
import 'package:pinsta/providers/all_posts.dart';
import 'package:provider/provider.dart';
class EditPostScreen extends StatefulWidget {
static String routeName = '/edit-post';
#override
State<EditPostScreen> createState() => _EditPostScreenState();
}
class _EditPostScreenState extends State<EditPostScreen> {
var form = GlobalKey<FormState>();
String? caption?? ;
void saveForm(int i, AllPosts myPosts) {
bool isValid = form.currentState!.validate();
if (isValid) {
form.currentState!.save();
print(caption);
myPosts.updatePost(i,caption);
FocusScope.of(context).unfocus();
form.currentState!.reset();
caption = null;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
Flexible(child: Text('updated', style: TextStyle(color: Colors.white, fontSize: 14.5))),
],
),
duration: Duration(seconds: 1),
),
);
}
}
#override
Widget build(BuildContext context) {
AllPosts postList1 = Provider.of <AllPosts> (context);
int i = ModalRoute.of(context)?.settings.arguments as int;
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 12.0,vertical: 18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset('assets/images/upload_image.png',height: 200,
width: 200,),
SizedBox(height: 50.0,),
Form(
key: form,
child: Column(
children: [
SizedBox(
height: 60.0,
),
TextFormField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.people, color: Colors.grey),
hintText: 'caption',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(24.0)
)
),
validator: (value) {
if (value == null)
return caption;
},
onSaved: (value) {caption = value;},
),
SizedBox(
height: 50.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: TextButton(
onPressed:() => saveForm(i,caption!),
child: Text(
'Update', style: TextStyle(fontSize: 17, fontWeight: FontWeight.bold, color: Colors.white),
),
),
)
),
),
],
),
),
],
),
),
),
);
}
}
This is the provider:
import 'package:flutter/material.dart';
import '../models/post.dart';
class AllPosts with ChangeNotifier {
List <Post> myPosts = [];
List<Post> getMyPosts() {
return myPosts;
}
void addPost(imageUrl, caption, username) {
myPosts.insert(0, Post(imageUrl: imageUrl, caption: caption, username:username));
notifyListeners();
}
void removePost(i) {
myPosts.removeAt(i);
notifyListeners();
}
void updatePost(i,caption ) {
myPosts[i].caption = caption;
notifyListeners();
}
}
You method void saveForm(int i, AllPosts myPosts) has AllPosts as the 2nd parameter but you are calling it with saveForm(i,caption!), passing a String (caption) as argument.

The argument type 'String?' can't be assigned to the parameter type

The argument type 'String?' can't be assigned to the parameter type 'String'.dart (argument_type_not_assignable.)
try{
var key = 'email';
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key],
_authData['password']
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} catch(error)
{
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
}
try{
await Provider.of<Authentication>(context, listen: false).logIn(
_authData['email'],
_authData['password']
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} catch (error)
{
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
}
Screenshot
Screenshot
This is a problem of null safety. Basically, your signUp method accepts a String as parameter, but you are passing a String? (the question mark indicated that the valute can be null). In order to solve this situation you have to check if _authData[key] and _authData['password'] (same also for logIn) are not null. Something like this:
try{
var key = 'email';
if(_authData[key] != null && _authData['password'] != null) {
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key]!,
_authData['password']!,
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} else {
throw Exception('Error');
}
} catch(error) {
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
Missing concrete implementation of 'State.build'.
Try implementing the missing method, or make the class abstract.dart(non_abstract_class_inherits_abstract_member)
signup_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/authentication.dart';
import 'home_screen.dart';
import 'login_screen.dart';
class SignupScreen extends StatefulWidget {
static const routeName = '/signup';
#override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final GlobalKey<FormState> _formKey = GlobalKey();
TextEditingController _passwordController = new TextEditingController();
Map<String, String> _authData = {
'email' : '',
'password' : ''
};
void _showErrorDialog(String msg)
{
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An Error Occured'),
content: Text(msg),
actions: <Widget>[
FlatButton(
child: Text('Okay'),
onPressed: (){
Navigator.of(ctx).pop();
},
)
],
)
);
}
Future<void> _submit() async
{
if(!_formKey.currentState!.validate())
{
return;
}
_formKey.currentState!.save();
try{
var key = 'email';
if(_authData[key] != null && _authData['password'] != null) {
await Provider.of<Authentication>(context, listen: false).signUp(
_authData[key]!,
_authData['password']!,
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} else {
throw Exception('Error');
}
} catch(error) {
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Signup'),
actions: <Widget>[
FlatButton(
child: Row(
children: <Widget>[
Text('Login'),
Icon(Icons.person)
],
),
textColor: Colors.white,
onPressed: (){
Navigator.of(context).pushReplacementNamed(LoginScreen.routeName);
},
)
],
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.limeAccent,
Colors.redAccent,
]
)
),
),
Center(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
height: 300,
width: 300,
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
//email
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value)
{
if(value!.isEmpty || !value.contains('#'))
{
return 'invalid email';
}
return null;
},
onSaved: (value)
{
_authData['email'] = value!;
},
),
//password
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value)
{
if(value!.isEmpty || value.length<=5)
{
return 'invalid password';
}
return null;
},
onSaved: (value)
{
_authData['password'] = value!;
},
),
//Confirm Password
TextFormField(
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: (value)
{
if(value!.isEmpty || value != _passwordController.text)
{
return 'invalid password';
}
return null;
},
onSaved: (value)
{
},
),
SizedBox(
height: 30,
),
RaisedButton(
child: Text(
'Submit'
),
onPressed: ()
{
_submit();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
color: Colors.blue,
textColor: Colors.white,
)
],
),
),
),
),
),
)
],
),
);
}
}
}
login_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'signup_screen.dart';
import 'home_screen.dart';
import '../models/authentication.dart';
class LoginScreen extends StatefulWidget {
static const routeName = '/login';
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final GlobalKey<FormState> _formKey = GlobalKey();
Map<String, String> _authData = {
'email' : '',
'password': ''
};
var email;
void _showErrorDialog(String msg)
{
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An Error Occured'),
content: Text(msg),
actions: <Widget>[
FlatButton(
child: Text('Okay'),
onPressed: (){
Navigator.of(ctx).pop();
},
)
],
)
);
}
Future<void> _submit() async
{
if(!_formKey.currentState!.validate())
{
return;
}
_formKey.currentState!.save();
try{
if(_authData[email] != null && _authData['password'] != null) {
await Provider.of<Authentication>(context, listen: false).logIn(
_authData['email']!,
_authData['password']!,
);
Navigator.of(context).pushReplacementNamed(HomeScreen.routeName);
} else {
throw Exception('Error');
}
} catch(error) {
var errorMessage = 'Authentication Failed. Please try again later.';
_showErrorDialog(errorMessage);
}}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
actions: <Widget>[
FlatButton(
child: Row(
children: <Widget>[
Text('Signup'),
Icon(Icons.person_add)
],
),
textColor: Colors.white,
onPressed: (){
Navigator.of(context).pushReplacementNamed(SignupScreen.routeName);
},
)
],
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.lightGreenAccent,
Colors.blue,
]
)
),
),
Center(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
height: 260,
width: 300,
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
//email
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value)
{
if(value!.isEmpty || !value.contains('#'))
{
return 'invalid email';
}
return null;
},
onSaved: (value)
{
_authData['email'] = value!;
},
),
//password
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value)
{
if(value!.isEmpty || value.length<=5)
{
return 'invalid password';
}
return null;
},
onSaved: (value)
{
_authData['password'] = value!;
},
),
SizedBox(
height: 30,
),
RaisedButton(
child: Text(
'Submit'
),
onPressed: ()
{
_submit();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
color: Colors.blue,
textColor: Colors.white,
)
],
),
),
),
),
),
)
],
),
);
}
}
Photo

How can I create a scrollable page using flutter where the children don't exceed the maxWidth of a parent container?

Problem
I have tried SingleChildListView and ListView widgets but the children end up spanning full width. I need the widgets to not exceed a maxWidth of 850px. Using a container with a width:850 or a BoxContraints(maxWidth:850) does not apply to the children inside the list view.
Desired Outcome
The form should be centered on the page but the scrollbar should be as far right as possible. If the user's mouse is on the form or in the white space to the left/right of the form, the user should retain the ability to scroll up/down.
SFUScaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Container(
constraints:
BoxConstraints(maxWidth: ThemeManager.getTheme().maxWidth),
child: Scrollbar(
isAlwaysShown: true,
controller: _scrollbar,
child: SingleChildScrollView(
controller: _scrollbar,
padding: EdgeInsets.all(15),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SFUSizedBox(height: 5),
Text(
"Secure File Upload Form",
style: ThemeManager.getTheme().formTitleStyle,
),
SFUSizedBox(height: 5),
Text(
"Quickly upload and send documents directly to the ${ThemeManager.getTheme().clientName} team",
style: ThemeManager.getTheme().formSubtitleStyle,
),
SFUSizedBox(height: 5),
Divider(),
SFUSizedBox(height: 5),
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Visibility(
visible: state.hasErrors,
child: FittedBox(
child: Row(
children: [
Icon(
LineIcons.exclamationCircle,
color: ThemeManager.getTheme().errorColor,
size: 30,
),
Text(
"Your form was not sent. Please correct the issues below and try again.",
style: ThemeManager.getTheme().errorStyle,
),
],
),
),
);
}),
Text(
"Tell us who you are",
style: ThemeManager.getTheme().formSectionTitleStyle,
),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
isLargeScreen
? _BuildNameLayout(direction: Axis.horizontal)
: _BuildNameLayout(direction: Axis.vertical),
SFUSizedBox(height: 5),
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Container(
width: isLargeScreen
? ThemeManager.getTheme().px2pt(400)
: ThemeManager.getTheme().px2pt(600),
child: PXFormField(
label: "Member ID:",
optional: true,
initalValue: state.formFields["member_id"] ?? "",
onChanged: (value) {
context
.read<FormCubit>()
.updateFormField('member_id', value);
},
),
);
},
),
SizedBox(height: ThemeManager.getTheme().px2pt(20)),
Divider(),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
Text(
"Share your contact details",
style: ThemeManager.getTheme().formSectionTitleStyle,
),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Container(
width: isLargeScreen
? ThemeManager.getTheme().px2pt(400)
: ThemeManager.getTheme().px2pt(600),
child: PXFormField(
initalValue: state.formFields["email"] ?? "",
label: "Email: *",
optional: false,
onChanged: (value) {
context
.read<FormCubit>()
.updateFormField('email', value);
},
validator: (value) {
if (!FieldValidator.validateEmail(value)) {
return "Please provide a valid email address.";
} else if (state.formErrors
.containsKey("email")) {
return state.formErrors['email'];
}
return null;
}),
);
},
),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Container(
width: isLargeScreen
? ThemeManager.getTheme().px2pt(400)
: ThemeManager.getTheme().px2pt(600),
child: PXFormField(
initalValue:
state.formFields["phone_number"] ?? "",
label: "Phone Number:",
optional: true,
onChanged: (value) {
context
.read<FormCubit>()
.updateFormField('phone_number', value);
},
),
);
},
),
SizedBox(height: ThemeManager.getTheme().px2pt(20)),
Divider(
thickness: 1.0,
),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
Text(
"Select the files that you would like to send",
style: ThemeManager.getTheme().formSectionTitleStyle,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Text(
state.formErrors['files'] != null
? state.formErrors['files'].toString()
: "",
style: ThemeManager.getTheme().errorStyle,
);
},
),
],
),
Text(
"Upload Your Files: *",
style: ThemeManager.getTheme().formLabelStyle,
),
SizedBox(
height: ThemeManager.getTheme().px2pt(15),
),
UploadFilesComponent(),
Container(
child: BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return Column(
children: new List.generate(
state.files.length,
(index) => FileCard(
//Add Progress value here for styling....
file: state.files[index],
fileIndex: index),
),
);
},
),
),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
Divider(),
SizedBox(height: ThemeManager.getTheme().px2pt(10)),
Text(
"Provide any background or instructions for the files you're sending",
style: ThemeManager.getTheme().formSectionTitleStyle),
SFUSizedBox(height: 20),
RichText(
text: TextSpan(
text: "Additional Information:",
style: ThemeManager.getTheme().formLabelStyle,
children: <TextSpan>[
TextSpan(
text: " (optional)",
style: ThemeManager.getTheme()
.formOptionalLabelStyle,
)
]),
),
SFUSizedBox(height: 30),
BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return TextFormField(
keyboardType: TextInputType.multiline,
maxLines: null,
minLines: 4,
onChanged: (value) {
context.read<FormCubit>().updateFormField(
'additional_information', value);
},
);
},
),
SFUSizedBox(height: 30),
Center(
child: Container(
width: ThemeManager.getTheme().px2pt(300),
height: ThemeManager.getTheme().px2pt(50),
child: BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return DarkOutlinedButton(
buttonText: "Send Your Files",
onpressed: () {
context.read<FormCubit>().validateForm();
_formKey.currentState!.validate();
if (!state.hasErrors) {
Navigator.pushNamedAndRemoveUntil(context,
"/submission-details", (_) => false);
}
},
);
},
),
),
),
SFUSizedBox(height: 30),
Divider(),
SFUSizedBox(height: 30),
Center(
child: Image.asset("images/powered_by_pensionx.png")),
Center(
child: TextButton(
onPressed: () async {
await showDialog(
context: context,
builder: (_) => ReportProblemModal(),
);
},
child: Text(
"Report a Problem",
style: TextStyle(
color: Theme.of(context).primaryColor),
),
),
)
],
),
),
),
),
),
),
),
);
class SFUSizedBox extends StatelessWidget {
final double height;
const SFUSizedBox({
required this.height,
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return SizedBox(height: ThemeManager.getTheme().px2pt(height));
}
}
class _BuildNameLayout extends StatelessWidget {
final Axis direction;
_BuildNameLayout({required this.direction});
#override
Widget build(BuildContext context) {
List<Widget> content = [
Expanded(
flex: this.direction == Axis.horizontal ? 3 : 0,
child: BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return PXFormField(
initalValue: state.formFields["first_name"] ?? "",
label: "First Name: *",
optional: false,
validator: (value) {
if (state.formErrors.containsKey("first_name")) {
return state.formErrors['first_name'];
}
return null;
},
onChanged: (value) {
context.read<FormCubit>().updateFormField('first_name', value);
},
);
},
),
),
SizedBox(width: 10),
Expanded(
flex: this.direction == Axis.horizontal ? 2 : 0,
child: BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return PXFormField(
initalValue: state.formFields["middle_initial"] ?? "",
label: "Middle Initial:",
optional: false,
onChanged: (value) {
context
.read<FormCubit>()
.updateFormField('middle_initial', value);
},
);
},
),
),
SizedBox(width: 10),
Expanded(
flex: this.direction == Axis.horizontal ? 3 : 0,
child: BlocBuilder<FormCubit, FormCubitState>(
builder: (context, state) {
return PXFormField(
initalValue: state.formFields["last_name"] ?? "",
label: "Last Name: *",
optional: false,
onChanged: (value) {
context.read<FormCubit>().updateFormField('last_name', value);
},
validator: (value) {
if (state.formErrors.containsKey("last_name")) {
return state.formErrors['last_name'];
}
return null;
},
);
},
),
),
];
if (this.direction == Axis.horizontal) {
return Container(
width: ThemeManager.getTheme().maxWidth,
child: Row(children: content));
}
if (this.direction == Axis.vertical) {
return Column(
mainAxisSize: MainAxisSize.min,
children: content,
);
}
// This shoudln't ever happen.
throw new Exception(
'Direction must be set to Axis.horizontal or Axis.vertical');
}
}
The image above has the following problems:
The white space to the left/right doesn't allow the user to scroll
The scroll bar needs to be as far to right as possible.
The form appears to be embedded into the page but I want it to feel like an entire page.

Flutter Error Message Bottom overloaded by 45 pixels

I want to create a login screen using Flutter.
This is my code so far:
Future showInformationDialog(BuildContext context) {
TextEditingController name = TextEditingController();
TextEditingController deadline = TextEditingController();
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Form(
child: Column(
children: <Widget>[
TextFormField(
controller: name,
maxLength: 40,
textAlign: TextAlign.left,
keyboardType: TextInputType.text,
autocorrect: false,
decoration: InputDecoration(
labelText: 'Name der Klausur: ',
border: OutlineInputBorder(),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Gib den Namen der Klausur ein!';
}
return null;
},
),
SizedBox(height: 20),
TextFormField(
controller: deadline,
maxLength: 8,
textAlign: TextAlign.left,
keyboardType: TextInputType.datetime,
autocorrect: false,
decoration: InputDecoration(
labelText: 'Deadline: ',
border: OutlineInputBorder(),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Gib das Datum der Klausur ein!';
}
return null;
},
),
SizedBox(height: 20),
DropDownFormField(
titleText: 'Priorität',
hintText: 'Bitte auswählen',
value: '',
dataSource: [
{
"display": "Niedrig",
"value": "Niedrig",
},
{
"display": "Mittel",
"value": "Mittel",
},
{
"display": "Hoch",
"value": "Hoch",
},
],
textField: 'display',
valueField: 'value',
),
SizedBox(height: 20),
],
),
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(name.text),
);
}
);
},
child: Text('Save'),
color: Colors.blue,
),
FlatButton(
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(deadline.text),
);
}
);
},
child: Text('Save'),
color: Colors.blue,
),
],
);
});
}
When the keyboard opens, it collides with the textfields -> I get an error:
Bottom overflowed by 49 pixels.
What could be the issue?
I have tried everything but I got stuck here.
SingleChildScrollView or resizeToAvoidBottomPadding: false didnt help me. Maybe I don't know how to use them correctly.
For any help I would be happy.
Is it me, or can't I find the code for your login screen? The error is thrown because there isn't enough place for your widget on the screen. Are you using a ListView or a Column? With a ListView you can scroll so if there isn't enough room for the content the user can scroll down to see what isn't on the screen.

Resources