Reputation: 351
I'm coding textfield with river_pod library as follows.
When I tapped each suffixIcon, it works both password and password-confirmation field and finally it figured out that each state
is only managed by single provider.
And wonder how should I manage this provider and consumer separately, and effectively.
//main.dart
import 'package:cards/view/textfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
ProviderScope(
child: MaterialApp(
title: 'Cards Demo',
home: RegisterWidget(),
),
),
);
}
class RegisterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(20, 50, 20, 0),
child: Column(
children: [
Container(
width: double.infinity,
height: 50,
// color: Colors.grey,
alignment: Alignment.topLeft,
child: Image.asset('images/logo.png'),
),
Container(
padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
margin: const EdgeInsets.only(top: 30),
width: double.infinity,
// color: Colors.blue,
child: Column(
children: [
const Align(
alignment: AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "email",
hintText: "type your email-adress",
suffixIcon: null,
),
),
Align(
alignment: const AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "password",
hintText: "set password",
suffixIcon: SuffixIconWidget()),
),
Align(
alignment: const AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "password-confirm",
hintText: "password for confirmation",
suffixIcon: SuffixIconWidget()),
),
],
),
),
],
),
));
}
}
//textfield.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
final mask = StateProvider<bool>((ref) => true);
class TextFieldCustom extends ConsumerWidget {
const TextFieldCustom({required this.labelText, required this.hintText, this.suffixIcon, Key? key}): super(key: key);
final String labelText;
final String hintText;
final Widget? suffixIcon;
@override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
child: TextFormField(
style: const TextStyle(
fontSize: 13,
),
obscureText: ObscureTextFunction(suffixIcon, ref),
decoration: InputDecoration(
labelText: labelText, //**
hintText: hintText, //**
suffixIcon: suffixIcon, //**
labelStyle: const TextStyle(
fontSize: 15,
color: Color.fromARGB(255, 219, 219, 219),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(2),
borderSide: const BorderSide(
color: Color.fromARGB(255, 219, 219, 219),
width: 1.0,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(2),
borderSide: const BorderSide(
color: Color.fromARGB(255, 219, 219, 219),
width: 1.0, //outlineの太さ
)),
),
));
}
}
bool ObscureTextFunction(suffixIcon, ref) {
if (suffixIcon == null) {
return false;
} else {
final bool isVisible = ref.watch(mask);
return isVisible ? false : true;
}
}
class SuffixIconWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(mask);
return IconButton(
icon: Icon(ref.watch(mask) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(mask.notifier).update((state) => !isVisible);
},
);
}
}
Additional Code
final mask = StateProvider<bool>((ref) => true);
final maskConfirm = StateProvider<bool>((ref) => true);
class SuffixIconWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(mask);
return IconButton(
icon: Icon(ref.watch(mask) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(mask.notifier).update((state) => !isVisible);
},
);
}
}
class SuffixIconWidgetConfirm extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(maskConfirm);
return IconButton(
icon: Icon(ref.watch(maskConfirm) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(maskConfirm.notifier).update((state) => !isVisible);
},
);
}
}
Upvotes: 0
Views: 353
Reputation: 191
For local states that are only important for the widget, I would just recommend you have a simple boolean in TextFieldCustom
and change it with setState.
Generally speaking though, for this widget to be correctly reusable with Riverpod, you should create a callback function onIconPressed(). Just like you are passing labelText, suffixIcon etc., in Flutter you can also pass functions like you do for buttons. Then for one provider to work on both widgets, it shouldn't be a provider of boolean, but instead of an object that holds two booleans.
Upvotes: 1