'Navigation from hookwidget screen to a nother hookwidget screen via button tap not working
I have a landing screen from which I tried to access authentication screens via respective buttons. The landing screen and the authentication screen extend HookWidget and HookConsumerWidget. I have these 2 problems that have left me frustrated and need your help.
The images are supposed to animate linearly and continuously. The animation is not working as I get only a static image that changes only upon hot reload.
Clicking on say the Login button to access the AuthScreen screen, returns error: "Hooks can only be called from the build method of a widget that mix-in.
LandingScreen:
class LandingScreen extends HookWidget {
LandingScreen({Key? key}) : super(key: key);
static const routeName = 'landingScreen';
final List<String> _images = [
'assets/images/shopping1.jpeg',
'assets/images/shopping2.jpeg',
];
@override
Widget build(BuildContext context) {
late Animation _animation;
final _animationController = useAnimationController(
duration: const Duration(seconds: 2),
);
useEffect(() {
_images.shuffle();
final _animationController = useAnimationController(
duration: const Duration(seconds: 20),
);
_animation =
CurvedAnimation(parent: _animationController, curve: Curves.linear)
..addListener(() {
_animationController.value;
})
..addStatusListener((animationStatus) {
if (animationStatus == AnimationStatus.completed) {
_animationController.reset();
_animationController.forward();
}
});
_animationController.forward();
}, const []);
return Scaffold(
body: Stack(
children: [
SizedBox(
width: double.infinity,
height: double.infinity,
child: Image.asset(
_images[0],
// 'assets/images/shopping2.jpeg',
fit: BoxFit.cover,
// alignment: FractionalOffset(_animation.value, 0),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
SizedBox(
height: 50,
),
Center(
child: Text(
'Welcome to',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
Center(
child: Text(
'Eleganza Mall',
style: TextStyle(
fontSize: 50,
color: Colors.white,
// color: Color(0XFF660000),
),
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: MyButton(
text: 'Login',
txtColor: Colors.white,
txtSize: 20,
bgColor: Colors.deepPurple,
onTap: () {
Navigator.pushReplacementNamed(
context, AuthScreen.routeName,
arguments: 'login');
},
),
),
const SizedBox(
width: 10,
),
Expanded(
child: MyButton(
text: 'Sign Up',
txtColor: Colors.white,
txtSize: 20,
bgColor: Colors.deepPurple,
onTap: () {
Navigator.pushReplacementNamed(
context, AuthScreen.routeName,
arguments: 'register');
},
),
),
],
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: MyButton(
text: 'Google Sign In',
txtColor: Colors.white,
txtSize: 20,
bgColor: Colors.deepPurple,
onTap: () {},
),
),
const SizedBox(
width: 10,
),
Expanded(
child: MyButton(
text: 'Sign in as Guest',
txtColor: Colors.white,
txtSize: 20,
bgColor: Colors.deepPurple,
onTap: () {},
),
),
],
),
),
const SizedBox(
height: 20,
),
],
),
],
),
);
}
}
AuthScreen
@override
Widget build(BuildContext context, WidgetRef ref) {
final authMode = ModalRoute.of(context)?.settings.arguments as String;
switch (authMode) {
case 'login':
_authMode.value = AuthMode.login;
break;
case 'register':
_authMode.value = AuthMode.register;
break;
case 'guest':
_authMode.value = AuthMode.guest;
break;
case 'google':
_authMode.value = AuthMode.google;
break;
}
return Scaffold(
body: Stack(
children: [
RotatedBox(
quarterTurns: 2,
child: WaveWidget(
config: CustomConfig(
durations: [35000, 11000, 10800, 6000],
colors: [
Colors.orangeAccent,
Colors.tealAccent,
Colors.pinkAccent,
Colors.deepPurpleAccent,
],
heightPercentages: [0.01, 0.02, 0.03, 0.1],
blur: const MaskFilter.blur(BlurStyle.solid, 0),
),
heightPercentange: 0.2,
size: const Size(double.infinity, double.infinity),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
height: 80,
),
Center(
child: _authMode.value == AuthMode.login
? const Text(
'Access Your Account',
style: TextStyle(
fontSize: 25,
),
)
: Row(
children: [
InkWell(
onTap: () => _showPicker(context),
child: CircleAvatar(
radius: 50,
backgroundImage: _imageFile.value == null
? null
: FileImage(
File(_imageFile.value!.path),
),
child: _imageFile.value == null
? const Icon(
Icons.camera,
// Icons.add_photo_alternate,
size: 30,
color: Colors.white,
)
: null,
),
),
const SizedBox(
width: 15,
),
const Text(
'Create an Account',
style: TextStyle(
fontSize: 25,
),
),
],
),
),
const SizedBox(
height: 30,
),
if (_authMode.value == AuthMode.register)
TextFormField(
onEditingComplete: () => FocusScope.of(context)
.requestFocus(_phoneFocusScope),
decoration: kTextInputDecoration.copyWith(
labelText: 'Fullname',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(
Icons.account_circle,
size: 30,
),
contentPadding: const EdgeInsets.all(10),
),
keyboardType: TextInputType.name,
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_phoneFocusScope);
},
validator: (value) {
if (value!.isEmpty || isNumeric(value)) {
return 'Only alphabet characters and cannot be blank';
}
return null;
},
onSaved: (value) {
name = value!;
},
),
const SizedBox(
height: 10,
),
if (_authMode.value == AuthMode.register)
TextFormField(
focusNode: _phoneFocusScope,
decoration: kTextInputDecoration.copyWith(
labelText: 'Phone Number',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(
Icons.phone,
size: 30,
),
contentPadding: const EdgeInsets.all(10),
),
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
onEditingComplete: () => FocusScope.of(context)
.requestFocus(_emailFocuScope),
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_emailFocuScope);
},
validator: (value) {
if (value!.isEmpty || value.trim().length < 10) {
return 'Cannot be blank or shorter than 10 chars';
}
return null;
},
onSaved: (value) {
phone = value!;
},
),
const SizedBox(
height: 10,
),
TextFormField(
key: const ValueKey('email'),
focusNode: _emailFocuScope,
validator: (value) {
if (!isEmail(value!)) {
return 'Please enter a valid email';
}
return null;
},
onSaved: (value) {
// _authData['email'] = value!;
email = value!;
},
textInputAction: TextInputAction.next,
onEditingComplete: () => FocusScope.of(context)
.requestFocus(_passwordFocusScope),
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_passwordFocusScope);
},
decoration: kTextInputDecoration.copyWith(
labelText: 'Email',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(
Icons.email,
size: 30,
),
contentPadding: const EdgeInsets.all(10),
),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(
height: 10,
),
TextFormField(
controller: _passwordController,
focusNode: _passwordFocusScope,
// onEditingComplete: _submit,
onEditingComplete: () => FocusScope.of(context)
.requestFocus(_confirmFocusScope),
obscureText: _isVisible.value,
key: const ValueKey('password'),
validator: (value) {
if (value!.isEmpty || value.length < 8) {
return 'Password cannot be empty and must be at least 8 chars!';
}
return null;
},
onSaved: (value) {
// _authData['password'] = value!;
password = value!;
},
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_confirmFocusScope);
},
decoration: kTextInputDecoration.copyWith(
labelText: 'Password',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(
Icons.lock,
size: 30,
),
suffixIcon: IconButton(
icon: _isVisible.value
? const Icon(Icons.visibility_off)
: const Icon(Icons.visibility),
onPressed: () {
_isVisible.value = !_isVisible.value;
},
),
contentPadding: const EdgeInsets.all(10),
),
),
const SizedBox(
height: 10,
),
if (_authMode.value == AuthMode.register)
TextFormField(
focusNode: _confirmFocusScope,
// controller: _passwordController,
textInputAction: TextInputAction.done,
// onFieldSubmitted: (_) {
// FocusScope.of(context)
// .requestFocus(_confirmFocusScope);
// },
// onEditingComplete: FocusScope.of(context)
// .unfocus(),
key: const ValueKey('confirm'),
obscureText: _isVisible.value,
validator: (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
return null;
},
decoration: kTextInputDecoration.copyWith(
labelText: 'Confirm Password',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(
Icons.lock,
size: 30,
),
suffixIcon: IconButton(
icon: _isVisible.value
? const Icon(Icons.visibility_off)
: const Icon(Icons.visibility),
onPressed: () {
_isVisible.value = !_isVisible.value;
},
),
contentPadding: const EdgeInsets.all(10),
),
),
const SizedBox(
height: 20,
),
MyButton(
text: _authMode.value == AuthMode.login
? 'Login'
: 'Sign Up',
txtColor: Colors.white,
txtSize: 20,
bgColor: Colors.deepPurple,
onTap: () {
FocusScope.of(context)
.unfocus(); // used to dismiss the keyboard
_submit();
_authMode.value == AuthMode.login
? ref
.read(authRepositoryProvider)
.login(email, password)
: ref.read(authRepositoryProvider).register(
context,
email,
password,
name,
phone,
);
},
)
],
),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Center(
child: TextButton(
onPressed: () {
_authMode.value == AuthMode.login
? _authMode.value = AuthMode.register
: _authMode.value = AuthMode.login;
},
child: Text(
'${_authMode.value == AuthMode.login ? 'No account? Sign Up' : 'Have Account? Login'} ',
style: const TextStyle(fontSize: 16),
),
),
),
],
),
],
),
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

