I am developing new application in flutter. This application works well in android simulator, android real device and in iOS simulator. In iOS real device application works well in first launch but when i restart the app it shows only the textfield. Please help me to solve this issue.
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:moonlight/screens/sign_in.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Moonlight',
theme: ThemeData(fontFamily: 'Prata'),
home: SignInScreen(),
);
}
}
sign_in.dart:
import 'package:flutter/material.dart';
import 'package:moonlight/screens/sign_up.dart';
import 'package:moonlight/utils/constants.dart';
import 'package:moonlight/widget/textButton.dart';
import 'package:moonlight/widget/textFiled.dart';
import '../services/dimensions.dart';
class SignInScreen extends StatefulWidget {
const SignInScreen({Key? key}) : super(key: key);
#override
State<SignInScreen> createState() => _SignInScreenState();
}
class _SignInScreenState extends State<SignInScreen> {
final TextEditingController emailController = new
TextEditingController();
final TextEditingController passwordController = new
TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize:
Size.fromHeight(Dimensions().getResponsiveSize(170)),
child: Container(
color: appBarColor,
child: AppBar(
backgroundColor: appBarColor,
toolbarHeight: Dimensions().getResponsiveSize(170),
centerTitle: true,
title: Column(
children: [
Container(
//color: Colors.red,
width: Dimensions().getResponsiveSize(200),
height: Dimensions().getResponsiveSize(40),
//width: 200,
//color: Colors.red,
child: Image.asset(
logoUrl,
fit: BoxFit.fitHeight,
//height: Dimensions().getResponsiveSize(50),
//width: Dimensions().getResponsiveSize(200),
//width: 50,
),
),
SizedBox(height:
Dimensions().getResponsiveSize(20),),
Text('Sign In',
style: TextStyle(
fontSize: Dimensions().getResponsiveSize(25),
fontWeight: FontWeight.bold
),
),
SizedBox(height: Dimensions().getResponsiveSize(5),),
Text('Welcome',
style: TextStyle(
fontSize: Dimensions().getResponsiveSize(15),
),
),
],
),
),
)),
bottomNavigationBar: GestureDetector(
onTap: () {
},
child: Container(
color: appBarColor,
height: Dimensions().getResponsiveSize(50),
child: Center(
child: Text(
'Go',
style: TextStyle(color: Colors.white, fontSize:
Dimensions().getResponsiveSize(15),
fontWeight: FontWeight.bold
),
)),
),
),
body: Padding(
padding: EdgeInsets.symmetric(horizontal:
Dimensions().getResponsiveSize(20)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFieldInput(
controller: emailController,
icon: Icons.email,
text: 'Email',
),
SizedBox(
height: Dimensions().getResponsiveSize(10),
),
TextFieldInput(
controller: passwordController,
icon: Icons.lock_rounded,
text: 'Password',
isObscure: true,
),
Row(
children: [
Spacer(),
TextButtonWidget(
onPressed:forgotPassword,
text: 'Forgot Password?',
size: Dimensions().getResponsiveSize(15),
color: appBarColor,
),
],
),
SizedBox(
height: Dimensions().getResponsiveSize(20),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
color: Colors.grey,
width: Dimensions().getResponsiveSize(70),
height: 1.2,
),
SizedBox(
width: Dimensions().getResponsiveSize(10),
),
Text(
'OR',
style: TextStyle(color: Colors.grey,
fontSize: Dimensions().getResponsiveSize(15)
),
),
SizedBox(
width: Dimensions().getResponsiveSize(10),
),
Container(
color: Colors.grey,
width: Dimensions().getResponsiveSize(70),
height: 1.2,
),
],
),
SizedBox(
height: Dimensions().getResponsiveSize(20),
),
TextButtonWidget(
onPressed: signUpScreen,
text: 'Sign Up',
size: Dimensions().getResponsiveSize(15),
color: appBarColor,
),
],
),
),
);
}
forgotPassword(){
}
signUpScreen(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SignUpScreen()),
);
}
}
dimensions.dart
import 'package:get/get.dart';
class Dimensions{
static double shortestSide = Get.size.shortestSide;
getResponsiveSize(dynamic size) {
dynamic x = (size/392.72727272727275) * 100;
return (shortestSide*x)/100;
}
}
Related
first of all, i do apologise if i am not describing the problem as thorough or as easy to understand as possible, forgive me as i just started learning how to build flutter chat app. i have the code below and i have integrated with firebase. i also enabled phone sign-in method and have input phone number for testing. what i am facing is that my app is able to bypass the registration screen and verification screen even though i have provided the wrong phone number and verification code. i have attached my code below and do appreciate all the help i can get.
// ignore_for_file: deprecated_member_use
import 'package:country_pickers/country.dart';
import 'package:country_pickers/country_pickers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:influential_brands_club/colors.dart';
import 'package:influential_brands_club/presentation/bloc/auth/auth_cubit.dart';
import 'package:influential_brands_club/presentation/bloc/phone_auth/phone_auth_cubit.dart';
import 'package:influential_brands_club/presentation/pages/phone_verification_page.dart';
import 'package:influential_brands_club/presentation/pages/set_initial_profile_page.dart';
import 'package:influential_brands_club/presentation/screens/home_screen.dart';
import 'package:influential_brands_club/presentation/widgets/theme/style.dart';
class RegistrationScreen extends StatefulWidget {
const RegistrationScreen({Key? key}) : super(key: key);
#override
State<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
static Country _selectedFilteredDialogCountry =
CountryPickerUtils.getCountryByPhoneCode("65");
String _countryCode = _selectedFilteredDialogCountry.phoneCode;
String _phoneNumber = "";
final TextEditingController _phoneAuthController = TextEditingController();
#override
void dispose() {
_phoneAuthController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: BlocConsumer<PhoneAuthCubit, PhoneAuthState>(
listener: (context, phoneAuthState) {
if (phoneAuthState is PhoneAuthSuccess) {
BlocProvider.of<AuthCubit>(context).loggedIn();
}
if (phoneAuthState is PhoneAuthFailure) {
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text("Invalid Code"),
Icon(Icons.error_outline)
],
),
),
));
}
}, builder: (context, phoneAuthState) {
if (phoneAuthState is PhoneAuthSmsCodeReceived) {
return PhoneVerificationPage(
phoneNumber: _phoneNumber,
);
}
if (phoneAuthState is PhoneAuthProfileInfo) {
return SetInitialProfileWidget(phoneNumber: _phoneNumber);
}
if (phoneAuthState is PhoneAuthLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
if (phoneAuthState is PhoneAuthSuccess) {
return BlocBuilder<AuthCubit, AuthState>(
builder: (context, authState) {
if (authState is Authenticated) {
return HomeScreen(
uid: authState.uid,
);
}
return Container();
});
}
return _bodyWidget();
}),
);
}
Widget _bodyWidget() {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 60),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const <Widget>[
Text(""),
Text("Verify your phone number",
style: TextStyle(
fontSize: 18,
color: yellowColor,
fontWeight: FontWeight.w500)),
Icon(
Icons.more_vert,
color: Colors.white,
)
],
),
const SizedBox(
height: 30,
),
const Text(
"IB Club will send an SMS message (carrier charges may apply) to verify your phone number. Enter your country code and phone number below:",
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
const SizedBox(
height: 30,
),
ListTile(
tileColor: primaryColor,
onTap: _openFilteredCountryPickerDialog,
title: _buildDialogItem(_selectedFilteredDialogCountry),
),
const SizedBox(
height: 8,
),
Row(
children: <Widget>[
Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1.5,
color: yellowColor,
))),
width: 80,
height: 42,
alignment: Alignment.center,
child: Text(_selectedFilteredDialogCountry.phoneCode,
style: const TextStyle(color: Colors.white)),
),
const SizedBox(
width: 12,
),
Expanded(
child: SizedBox(
height: 40,
child: TextField(
controller: _phoneAuthController,
decoration: const InputDecoration(
hintText: "Phone Number",
hintStyle: TextStyle(color: Colors.white54),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: darkPrimaryColor),
)),
cursorColor: Colors.white,
style: const TextStyle(color: Colors.white)),
),
),
],
),
const SizedBox(
width: 8,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: MaterialButton(
color: yellowColor,
onPressed: _submitVerifyPhoneNumber,
child: const Text(
"Next",
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
),
)
])));
}
void _openFilteredCountryPickerDialog() {
showDialog(
context: context,
builder: (_) => Theme(
data: Theme.of(context).copyWith(
primaryColor: primaryColor,
),
child: CountryPickerDialog(
titlePadding: const EdgeInsets.all(8.0),
searchCursorColor: Colors.black,
searchInputDecoration: const InputDecoration(
hintText: "Search",
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: darkPrimaryColor),
)),
isSearchable: true,
title: const Text("Select your phone code",
style: TextStyle(color: yellowColor)),
onValuePicked: (Country country) {
setState(() {
_selectedFilteredDialogCountry = country;
_countryCode = country.phoneCode;
});
},
itemBuilder: _buildDialogItem,
),
));
}
Widget _buildDialogItem(Country country) {
return Container(
height: 40,
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: primaryBlack, width: 1),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CountryPickerUtils.getDefaultFlagImage(country),
const SizedBox(
height: 8.0,
),
Text(" +${country.phoneCode} "),
const SizedBox(
height: 8.0,
),
SizedBox(width: 155, child: Text(country.name)),
const Spacer(),
const Icon(Icons.arrow_drop_down)
],
),
);
}
void _submitVerifyPhoneNumber() {
if (_phoneAuthController.text.isNotEmpty) {
_phoneNumber = "+$_countryCode${_phoneAuthController.text}";
BlocProvider.of<PhoneAuthCubit>(context).submitVerifyPhoneNumber(
phoneNumber: _phoneNumber,
);
}
}
}
The following code works fine where the scrolling of the list view scrolls properly without running over into other widgets
when tested on Andoird emulator (on Windows).
But when tested on IOS emulator (on a MAC), the list over scrolls to the top and runs over the widgets on top of it.
Is there anything speific that needs to be done when it comes to IOS to address this?
Please see following video which I recorded to show the issue in scrolling.
https://imgur.com/a/1SbsNBL
I've added the whole block of code below in the event other widgets are causing this.
App bar code is held in another file but it is not affected by this issue anyway.
The listview widget is at the end of following code block within the Expanded widget. Thanks.
import 'dart:io';
import 'package:amex/dialog.dart';
import 'package:flutter/material.dart';
import 'account_details.dart';
import 'app_bar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int navIndex = 0;
selectTab(int index) {
setState(() {
navIndex = index;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color(0xff020B2A),
bottomNavigationBar: BottomNavigationBar(
onTap: selectTab,
backgroundColor: Color(0xff2A2E3B),
selectedItemColor: Color(0xff2F6DC8),
unselectedItemColor: Color(0xff868993),
currentIndex: navIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.money),
label: 'Statements',
),
BottomNavigationBarItem(
icon: Icon(Icons.star),
label: 'Membership',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_balance),
label: 'Account',
),
],
),
appBar: getAppBar(),
body: Column(
children: [
Center(
child: Column(
children: [
SizedBox(height: 30),
Text(
'Good Evening',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
SizedBox(height: 18),
Text(
'NAME',
style: TextStyle(
color: Colors.white,
fontSize: 28,
),
),
SizedBox(height: 18),
Text(
'Member Since \'18\'',
style: TextStyle(
color: Colors.white70,
fontSize: 10,
),
),
],
),
),
SizedBox(height: 30),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 16.0, bottom: 16.0),
child: Text(
'Account',
style: TextStyle(
color: Colors.white70,
fontSize: 16,
),
),
),
),
Expanded(
child: ListView.builder(
itemCount: accountTitles.length,
itemBuilder: (context, index) {
String title = accountTitles[index].title;
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.5,
color: Color(0xff868993),
),
),
),
child: ListTile(
tileColor: Color(0xff1B223E),
onTap: () => Platform.isIOS
? showDialogForIOS(context, title)
: showDialogForAndroid(context, title),
leading: Icon(
accountTitles[index].leadingIcon,
color: Colors.white,
),
title: Text(
accountTitles[index].title,
style: TextStyle(color: Colors.white),
),
trailing: Icon(accountTitles[index].trailingIcon,
color: Colors.white),
),
);
},
),
),
],
),
),
);
}
}
I want to have a custom sliver appBar with a search bar in it. I made a normal app bar that looks like this : But I want that when we scroll down, the app bar looks like that :
Actually, the code of the normal app bar is just a green AppBar of elevation: 0 and just below I add my Header(). Here's the code of my Header :
class Header extends StatefulWidget {
String title;
IconData icon;
Header({#required this.title, #required this.icon});
#override
_HeaderState createState() => _HeaderState();
}
class _HeaderState extends State<Header> {
TextEditingController _editingController;
#override
void initState() {
super.initState();
_editingController = TextEditingController();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return PreferredSize(
preferredSize: size,
child: Container(
margin: EdgeInsets.only(bottom: kDefaultPadding * 2.5),
height: size.height*0.2,
child: Stack(
children: [
Container(
height: size.height*0.2-27,
width: size.width,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(36),
bottomRight: Radius.circular(36),
)
),
child: Align(
alignment: Alignment.topCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(widget.title, style: Theme.of(context).textTheme.headline4.copyWith(color: Colors.white, fontWeight: FontWeight.bold)),
SizedBox(width: 20,),
Icon(widget.icon, size: 40, color: Colors.white,)
],
)),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
alignment: Alignment.center,
margin: EdgeInsets.symmetric(horizontal: kDefaultPadding),
padding: EdgeInsets.symmetric(horizontal: kDefaultPadding),
height: 54,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [BoxShadow(
offset: Offset(0, 10),
blurRadius: 50,
color: Theme.of(context).primaryColor.withOpacity(0.23),
)]
),
child: Row(
children: [
Expanded(
child: TextField(
controller: _editingController,
textAlignVertical: TextAlignVertical.center,
onChanged: (_) => setState(() {}),
decoration: InputDecoration(
hintText: 'Search',
hintStyle: TextStyle(color: Theme.of(context).primaryColor.withOpacity(0.5)),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
_editingController.text.trim().isEmpty ? IconButton(
icon: Icon(Icons.search, color: Theme.of(context).primaryColor.withOpacity(0.5)),
onPressed: null) :
IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
icon: Icon(Icons.clear, color: Theme.of(context).primaryColor.withOpacity(0.5)),
onPressed: () => setState(() {
_editingController.clear();
})),
],
),
),
)
],
),
),
);
}
#override
void dispose() {
_editingController.dispose();
super.dispose();
}
}
Any help to build this is welcome.
I've made a simple example to show the main logic.
Create your own SliverPersistentHeaderDelegate and calculate shrinkFactor.
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white70,
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
floating: false,
delegate: SearchHeader(
icon: Icons.terrain,
title: 'Trees',
search: _Search(),
),
),
SliverFillRemaining(
hasScrollBody: true,
child: ListView(
physics: NeverScrollableScrollPhysics(),
children: [
Text('some text'),
Placeholder(
color: Colors.red,
fallbackHeight: 200,
),
Container(
color: Colors.blueGrey,
height: 500,
)
],
),
)
],
),
);
}
}
class _Search extends StatefulWidget {
_Search({Key key}) : super(key: key);
#override
__SearchState createState() => __SearchState();
}
class __SearchState extends State<_Search> {
TextEditingController _editingController;
#override
void initState() {
super.initState();
_editingController = TextEditingController();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 5),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: TextField(
controller: _editingController,
// textAlignVertical: TextAlignVertical.center,
onChanged: (_) => setState(() {}),
decoration: InputDecoration(
hintText: 'Search',
hintStyle: TextStyle(
color: Theme.of(context).primaryColor.withOpacity(0.5)),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
_editingController.text.trim().isEmpty
? IconButton(
icon: Icon(Icons.search,
color: Theme.of(context).primaryColor.withOpacity(0.5)),
onPressed: null)
: IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
icon: Icon(Icons.clear,
color: Theme.of(context).primaryColor.withOpacity(0.5)),
onPressed: () => setState(
() {
_editingController.clear();
},
),
),
],
),
);
}
}
class SearchHeader extends SliverPersistentHeaderDelegate {
final double minTopBarHeight = 100;
final double maxTopBarHeight = 200;
final String title;
final IconData icon;
final Widget search;
SearchHeader({
#required this.title,
this.icon,
this.search,
});
#override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
var shrinkFactor = min(1, shrinkOffset / (maxExtent - minExtent));
var topBar = Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
alignment: Alignment.center,
height:
max(maxTopBarHeight * (1 - shrinkFactor * 1.45), minTopBarHeight),
width: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(title,
style: Theme.of(context).textTheme.headline4.copyWith(
color: Colors.white, fontWeight: FontWeight.bold)),
SizedBox(
width: 20,
),
Icon(
icon,
size: 40,
color: Colors.white,
)
],
),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(36),
bottomRight: Radius.circular(36),
)),
),
);
return Container(
height: max(maxExtent - shrinkOffset, minExtent),
child: Stack(
fit: StackFit.loose,
children: [
if (shrinkFactor <= 0.5) topBar,
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: EdgeInsets.only(
bottom: 10,
),
child: Container(
alignment: Alignment.center,
child: search,
width: 200,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
blurRadius: 10,
color: Colors.green.withOpacity(0.23),
)
]),
),
),
),
if (shrinkFactor > 0.5) topBar,
],
),
);
}
#override
double get maxExtent => 230;
#override
double get minExtent => 100;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}
TextFormField is not working properly, its blinking continuously and it doesn't allow me to write anything, as I tap on the TextFormField my keyboard appears for a second and disappear instantly. I am confused what wrong I have done with my code, I've matched my code with previous working code, but still getting this behaviour .
Here is my code.
class ComingSoonState extends State<ComingSoon> {
String language;
TextEditingController _textEdititingController ;
#override
void initState() {
_textEdititingController = new TextEditingController(); //Initialised TextEditingController
super.initState();
}
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final formData = new Form(
key: widget._formKey,
child: new Container(
padding: const EdgeInsets.only(
left: 35.0,
right: 35.0),
child: new Column(
children: <Widget>[
new Theme(
data: theme.copyWith(primaryColor: Colors.black54),
child: new TextFormField(
controller: _textEdititingController, //ADDED CONTROLLER HERE
style: const TextStyle(color: Colors.black54),
decoration: new InputDecoration(
labelText: 'Amount',
labelStyle: const TextStyle(color: Colors.black54)
),
// validator: this._validateEmail,
validator: (val) {
return val.isEmpty
? "Please enter amount"
: null;
},
onSaved: (String value) {
// this._data.email = value;
this.language = value;
}
),
),
],
),
),
);
return Scaffold(
appBar: new AppBar(
leading: null,
title: const Text('Send Money', style: const TextStyle(
color: Colors.white
),
),
),
body: new Container(
color: Colors.grey[300],
child: new ListView(
children: <Widget>[
new Container(
child: new Column(
children: <Widget>[
new Container(
height: 60.0 ,
padding: const EdgeInsets.all(5.0),
child: new Card(
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text("Available balance in wallet", style:
new TextStyle(color: Colors.black54,
fontSize: 16.0
),),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text("123 KSH", style:
new TextStyle(color: Colors.blueAccent,
fontSize: 16.0
),),
),
],
),
),
) ,
new Container(
//height: 300.0,
padding: const EdgeInsets.all(5.0),
child: new Card(
child: new Container(
child: new Center(
child: new Column(
children: <Widget>[
formData
],
),
),
),
),
)
],
)
),
],
),
),
);
}
}
I added a floating action button that presents a dialog that will show what you entered into the TextField (using the controller). I'm not sure what form key you were passing in before but making the GlobalKey instance a member variable eliminates the keyboard present/dismiss issue.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String language;
TextEditingController _textEditingController;
final _formKey = GlobalKey<FormState>();
#override
void initState() {
_textEditingController =
TextEditingController(); //Initialised TextEditingController
super.initState();
}
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final formData = Form(
key: _formKey,
child: Container(
padding: const EdgeInsets.only(left: 35.0, right: 35.0),
child: Column(
children: <Widget>[
Theme(
data: theme.copyWith(primaryColor: Colors.black54),
child: TextFormField(
controller: _textEditingController,
//ADDED CONTROLLER HERE
style: const TextStyle(color: Colors.black54),
decoration: InputDecoration(
labelText: 'Amount',
labelStyle: const TextStyle(color: Colors.black54)),
// validator: this._validateEmail,
validator: (val) {
return val.isEmpty ? "Please enter amount" : null;
},
onSaved: (String value) {
// this._data.email = value;
language = value;
}),
),
],
),
),
);
return Scaffold(
appBar: AppBar(
leading: null,
title: const Text(
'Send Money',
style: const TextStyle(color: Colors.white),
),
),
body: Container(
color: Colors.grey[300],
child: ListView(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
height: 60.0,
padding: const EdgeInsets.all(5.0),
child: Card(
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
"Available balance in wallet",
style: TextStyle(
color: Colors.black54, fontSize: 16.0),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
"123 KSH",
style: TextStyle(
color: Colors.blueAccent, fontSize: 16.0),
),
),
],
),
),
),
Container(
//height: 300.0,
padding: const EdgeInsets.all(5.0),
child: Card(
child: Container(
child: Center(
child: Column(
children: <Widget>[formData],
),
),
),
),
)
],
)),
],
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog with the
// text the user has typed into our text field.
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the user has typed in using our
// TextEditingController
content: Text(_textEditingController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: Icon(Icons.text_fields),
),
);
}
}
I'm new to flutter and dart. I am trying to learn both by developing an app. I have taken the udacity course but it only gave me the basics. What I want to know is if it is possible to handle the appBar code separately.
Currently, this is what I have:
class HomePage extends StatelessWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
),
body: new Center(
child: Text('Hello World!'),
),
);
}
}
However, I would like to handle the appbar code separately as I believe it can swell a bit more. I have tried something like this:
class HomePage extends StatelessWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: MyAppBar(),
body: new Center(
child: Text('Hello World!'),
),
);
}
}
class MyAppBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
);
}
}
But then I'm getting this message:
The argument type 'MyAppBar' can't be assigned to the parameter type 'PreferredSizeWidget'
I have an intuition that this might not be possible. As I said, I'm new to flutter and dart and I have tried looking in the documentation and in other posts to no avail. Sorry if this seems stupid. I would just really like for someone to point me to the documentation, if there is any, on how to achieve this kind of things or any resource that can help me better understand how this works.
For your kind and valuable help, many thanks in advance!
the appBar widget must implement the PreferredSizeWidget class so you have to :
class MyAppBar extends StatelessWidget implements PreferredSizeWidget
and then you have to implemt this method also
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
Full Example :
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
#override
Widget build(BuildContext context) {
return new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
);
}
#override
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
#override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.blueGrey,
title: Text('News App'),
centerTitle: true,
leading: Icon(Icons.menu ),
);
}
#override
// TODO: implement preferredSize
Size get preferredSize => new Size.fromHeight(48);
}