Flutter Provider.of and search - flutter

I am a beginner in flutter and app development. I have a problem. I am using Provider.of in order to get my data. I am getting data and showing it in ListView.builder with no problem. But I want to make a search on my list.
Please refer to code below
class RecipeList extends StatefulWidget {
#override
_RecipeListState createState() => _RecipeListState();
}
class _RecipeListState extends State<RecipeList> {
List<Recipe>showList =List();//creating my list of searched data
#override
Widget build(BuildContext context) {
//getting my recipe list in order to show them
final recipes = Provider.of<List<Recipe>>(context);
showList=recipes;
final user = Provider.of<User>(context);
String _image;
Widget myImage(int index,)
{
if(recipes[index].image == ''){
return Image.asset('images/no_image.jpg');
}
else{
return
FadeInImage.assetNetwork(
width: 300,
height: 250,
placeholder: 'images/loading.webp',
image: recipes[index].image,
);
}
}
return StreamBuilder<UserData>(
stream:DatabaseService(uid: user.uid).userData,
builder: (context,snapshot){
if(snapshot.hasData) {
UserData userdata = snapshot.data;
if (userdata.is_admin == true) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Colors.blue[200], Colors.orange[100]])),
child: Scaffold(
appBar: AppBar(
title: Text('Recipes'),
backgroundColor: Colors.transparent,
elevation: 0,
),
backgroundColor: Colors.transparent,
body: Column(
children: <Widget>[
Material(
elevation: 0,
color: Colors.transparent,
child: TextField(
onChanged: (val) {
val = val.toLowerCase();
setState(() {
showList = recipes.where((recipe){
var title = recipe.name.toLowerCase();
return title.contains(val);
}).toList();
});
},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(25.0)))),
),),
SizedBox(height: 15,),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: showList.length,
itemBuilder: (context, index) {
if (recipes[index].image == null) {
String _image = 'images/new.png';
}
else {
_image = recipes[index].image;
}
// print(recipes[index].image);
return Column(
children: <Widget>[
SlimyCard(
color: Colors.teal[200],
width: 300,
topCardHeight: 350,
bottomCardHeight: 300,
borderRadius: 15,
topCardWidget: Column(
children: <Widget>[
Text(recipes[index].name[0]
.toUpperCase() +
recipes[index].name.substring(1),
style: TextStyle(
fontSize: 35,
color: Colors.white,
fontWeight: FontWeight.bold,
),),
ClipRRect(borderRadius: BorderRadius
.circular(25.0),
child: myImage(index)
),
// Image.network('https://www.bbcgoodfood.com/sites/default/files/recipe-collections/collection-image/2013/05/chorizo-mozarella-gnocchi-bake-cropped.jpg')),
],
),
bottomCardWidget: SingleChildScrollView(
child: Column(
children: <Widget>[
Text('Ingredients',
style: TextStyle(
fontSize: 25,
color: Colors.white
),),
SizedBox(height: 5,),
Text(recipes[index].ingredients,
style: TextStyle(
fontSize: 16
),),
SizedBox(height: 20,),
Text('Recipe',
style: TextStyle(
fontSize: 25
,
color: Colors.white
),),
SizedBox(height: 5,),
Text(recipes[index].recipe,
style: TextStyle(
fontSize: 16
),),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(7.0),
//side: BorderSide(color: Colors.orange)
),
color: Color.fromRGBO(
233, 217, 108, 1),
onPressed: () async {
final CollectionReference recipecollection = Firestore
.instance.collection(
'recipe');
await recipecollection.document(
recipes[index].id).delete();
StorageReference firestoreStorageref = await FirebaseStorage
.instance
.getReferenceFromUrl(
recipes[index].image);
firestoreStorageref.delete();
},
child: Text(
'Delete'
),
)
],
),
),
slimeEnabled: false,
),
SizedBox(height: 25,)
],
);
},
)),
],
)
),
);
}
I want to show this list on the search and modify it. first I fill it with data from the provider.
I have created a TextField for Search the onChanged method filters the typed value and returns a list. When I print in onChanged function it is working.
I am showing my list with ListView, when I print the size of showList in onChanged function, it filters and gives the right value but when I use it for itemCount it never changes

You can use searchable_dropdown instead of the TextField. You can assign the list to it and it will search the list based on the to string method so you have to override it.
Refer the link to the dependency: https://pub.dev/packages/searchable_dropdown.

Related

search by username function in my flutter application using firebase returns a Future<dynamic> instance

i have a chatting application and i want to do a search function where the user can enter into a textfield another users username and to show the searched users username and name so the user can message them,
the problem i have is that when i retrieved from my firebase the user with the same username entered it returned a Future<dynamic> instance which then results in an error in using docs: "The getter 'docs' isn't defined for the type 'Future<dynamic>' "
here is my code
class _search extends State<search> {
TextEditingController searchController = new TextEditingController();
late Future<dynamic> searchResult;
bool haveUserSearched =false;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("search for user"),
centerTitle: true,
),
body: Container(
child: Column(
children: [
Container(
color: Color(0xfffffefa),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
// GestureDetector(
// onTap: (){
// print(getUserByUsername(searchController.text));
// },
// child:
Expanded(child: TextField(
controller: searchController,
style: TextStyle(color: Color(0xffBFBBB7)),
onSubmitted: (value){
print(getUserByUsername(searchController.text));
},
decoration: InputDecoration(
hintText: "search by username",
hintStyle: TextStyle(color: Color(0xffBFBBB7)),
border: InputBorder.none,
prefixIcon: Icon(Icons.search,color: Color(0xffBFBBB7),),
),
),
),
//),
],
),
),
],
),
),
);
}
//-------methods and widgets-------
getUserByUsername(String username) async {
return await FirebaseFirestore.instance.collection('users').where('name',isEqualTo: username).get();
}
Widget userTile(String name,String username){
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
color: Colors.white,
fontSize: 16
),
),
Text(
username,
style: TextStyle(
color: Colors.white,
fontSize: 16
),
)
],
),
Spacer(),
GestureDetector(
onTap: (){
//sendMessage(userName);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12,vertical: 8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(24)
),
child: Text("Message",
style: TextStyle(
color: Colors.white,
fontSize: 16
),),
),
)
],
),
);
}
Widget userList(){
return haveUserSearched ? ListView.builder(
shrinkWrap: true,
itemCount: 1, ///?
itemBuilder: (context, index){
return userTile(
searchResult.docs[index].data['name'], //the error here is in docs "The getter 'docs' isn't defined for the type 'Future<dynamic>' "
searchResult.docs[index].data["username"],
);
}) : Container();
}
}
searchResult is a Future, a representation of an eventual result (or error) from an asynchronous operation. You need to wait for the result, which you can do in various ways, such as await or FutureBuilder. In this circumstance, you may opt to choose the latter.
Please see Asynchronous programming: futures, async, await for more.
Use futureBuilder inside Column and pass fetched data like Widget userList(users) {
It can be like
class _search extends State<search> {
TextEditingController searchController = new TextEditingController();
bool haveUserSearched = false;
late Future<dynamic> searchResult = getUserByUsername(searchController.text);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("search for user"),
centerTitle: true,
),
body: Container(
child: Column(
children: [
Container(
color: Color(0xfffffefa),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Expanded(
child: TextField(
controller: searchController,
style: TextStyle(color: Color(0xffBFBBB7)),
onSubmitted: (value) {
searchResult = getUserByUsername(searchController.text);
setState(() {});
},
decoration: InputDecoration(
hintText: "search by username",
hintStyle: TextStyle(color: Color(0xffBFBBB7)),
border: InputBorder.none,
prefixIcon: Icon(
Icons.search,
color: Color(0xffBFBBB7),
),
),
),
),
],
),
),
FutureBuilder(
future: searchResult,
builder: (context, snapshot) {
if (snapshot.hasData) {
return userList(snapshot.data);
}
return Text("handle other state");
},
),
],
),
),
);
}
//-------methods and widgets-------
getUserByUsername(String username) async {
final result = await FirebaseFirestore.instance
.collection('users')
.where('name', isEqualTo: username)
.get();
User myUser = User(name: result['name'] .....) //get user from Map.. it cant be..
return myUser;
}
Widget userTile(String name, String username) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(color: Colors.white, fontSize: 16),
),
Text(
username,
style: TextStyle(color: Colors.white, fontSize: 16),
)
],
),
Spacer(),
GestureDetector(
onTap: () {
//sendMessage(userName);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(24)),
child: Text(
"Message",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
)
],
),
);
}
Widget userList(user) {
return haveUserSearched
? userTile(
user.name,
user.username,
)
: Container();
}
}

Hi! I'm trying to implement the same functionality duolingo in flutter

I'm trying to implement the same functionality, where word choices are offered as separate buttons and by clicking on them they are moved to the line, creating a sentence. Just like duolingo.
Example
I started doing it through TextFiled and text, but something tells me that's not a good solution.
How would you implement something like this?
import 'package:flutter/material.dart';
class Screen6_1_3 extends StatefulWidget {
const Screen6_1_3({super.key});
#override
State<Screen6_1_3> createState() => _Screen6_1_3State();
}
class _Screen6_1_3State extends State<Screen6_1_3> {
String textOne = "Bread";
var colorite = Colors.white;
TextEditingController textarea = TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.blue,
leading: GestureDetector(
child: Icon(
Icons.close,
color: Colors.white,
),
onTap: () {
Navigator.pushNamedAndRemoveUntil(
context, "home", (route) => false);
},
),
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 70,
height: 50,
decoration: BoxDecoration(
color: const Color.fromARGB(255, 226, 226, 226),
border: Border.all(
color: const Color.fromARGB(255, 123, 123, 123),
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
child: TextField(
enableSuggestions: false,
autocorrect: false,
controller: textarea,
maxLines: 1,
readOnly: false,
decoration: const InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color.fromARGB(255, 123, 123, 123))),
),
onTap: () {
setState(() {
textarea.clear();
textOne = 'Bread';
colorite = Colors.white;
});
},
),
),
],
),
Row(
children: [
SizedBox(
height: 20,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
setState(() {
if (textarea.text.isEmpty) {
insert('Bread');
textOne = 'Bread';
colorite = Colors.transparent;
}
});
},
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.white)),
child: Text(
textOne,
style: TextStyle(
color: colorite,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
],
),
);
}
void insert(String content) {
var text = textarea.text;
var pos = textarea.selection.start;
textarea.value = TextEditingValue(
text: text.substring(0, pos) + content + text.substring(pos),
selection: TextSelection.collapsed(offset: pos + content.length),
);
}
}
It will be pretty easy to implement if you use Draggable widgets for the words and DragTarget for the textfields.
Youtube Tutorial: https://www.youtube.com/watch?v=QzA4c4QHZCY
And a great example you might relate to :
https://mobikul.com/draggable-widget-in-flutter/
I'd recommend trying to watch the video first to get an idea about how Draggable widget works and then trying to implement it in your project by taking inspiration from the article that I've provided.

List of text in one Card using ListView.builder twice and for loop?

With my current code, my list is put into separate cards. I need it to be in one. I'm using two ListView.builders and a loop. I believe that's what's causing the problem. Please tell me if I'm wrong.
Every time the user taps submit on my second TextField a new TextField appears, functionality I would like to keep one way or another.
I'm just staring out so any help if appreciated.
My end goal is to have a bullet point list but the bullet points aren't important right now.
Here's my code:
class PostNote extends StatefulWidget {
User user;
PostNote({
required this.user,
});
#override
State<PostNote> createState() => _PostNoteState();
}
class _PostNoteState extends State<PostNote> {
FirebaseFirestore firestore = FirebaseFirestore.instance;
TextEditingController titleController = TextEditingController();
final List<TextField> _textFields = [];
final List<TextEditingController> _controllers = [];
bool loading = false;
#override
void initState() {
super.initState();
_addTextField();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFF162242),
elevation: 0,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
children: [
Text(
"Title",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10, right: 10),
child: TextField(
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),
),
textInputAction: TextInputAction.next,
style: TextStyle(
color: Color(0xFF192A4F),
fontSize: 18,
),
controller: titleController,
autofocus: true,
),
),
SizedBox(
height: 30,
),
Text(
"Notes",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
child: ListView.builder( // HERE
shrinkWrap: true,
itemCount: _textFields.length,
itemBuilder: (_, index) {
return _textFields[index];
},
),
),
SizedBox(
height: 50,
),
loading
? Center(
child: CircularProgressIndicator(),
)
: Container(
height: 50,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
child: Text(
"Add Note",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF162242)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
onPressed: () async {
for (var notesController in _controllers) // HERE {
if (titleController.text == "" ||
notesController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
await FirestoreServiceEdit().insertNote(
titleController.text,
notesController.text,
widget.user.uid);
CollectionReference notes =
firestore.collection('notes');
QuerySnapshot allResults = await notes.get();
allResults.docs.forEach((DocumentSnapshot result) {
print(result.data());
});
if (!mounted) return;
setState(() {
loading = false;
});
Navigator.pop(context);
}
}
}),
),
]),
),
),
),
);
}
void _addTextField() {
final notesController = TextEditingController();
_textFields.add(
TextField(
decoration: InputDecoration(
prefix: Icon(
Icons.circle,
size: 8,
color: Colors.black,
),
),
autofocus: true,
controller: notesController,
onSubmitted: (_) => setState(() => _addTextField()),
),
);
_controllers.add(notesController);
}
}
class FirestoreServiceEdit{
FirebaseFirestore firestore = FirebaseFirestore.instance;
Future insertNote(String title, String notes, String? userId,)async{
try{
await firestore.collection('notes').add({
"title":title,
"notes":notes,
"userId":userId
});
} catch (e) {}
}
}
class NoteModelEdit {
String id;
String title;
String notes;
String userId;
NoteModelEdit({
required this.id,
required this.title,
required this.notes,
required this.userId
});
factory NoteModelEdit.fromJson(DocumentSnapshot snapshot){
return NoteModelEdit(
id: snapshot.id,
title: snapshot['title'],
notes: snapshot['notes'],
userId: snapshot['userId']
);
}
}
Home screen:
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("notes")
.where('userId', isEqualTo: user.uid)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.docs.length > 0) {
return ListView.builder( // HERE
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
NoteModelEdit note =
NoteModelEdit.fromJson(snapshot.data.docs[index]);
return Card(
margin: EdgeInsets.only(top: 18, left: 15, right: 15),
child: Column(children: [
ListTile(
title: Center(
child: Container(
padding: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 0.5),
),
),
child: Text(
note.title,
textWidthBasis: TextWidthBasis.longestLine,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => EditNoteScreen(),
));
},
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
note.notes,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700),
),
),
SizedBox(
height: 15,
),
]),
);
});
Thank you for your time!
You will need to augment your logic to look at all the TextFields at the same time rather than one at a time and inserting a note for each.
if (titleController.text.isEmpty ||
_controllers.any((element) => element.text.isEmpty)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
}
await FirestoreServiceEdit().insertNote(
titleController.text,
_controllers.map((element) => element.text).join("\n"),
widget.user.uid);
you can do like this :
Widget listInCard() {
List testList = ["note1", "note2", "note3"];
return Card(
color: Colors.blue.shade200,
elevation: 5,
child: ListView.builder(
itemCount: testList.length,
itemBuilder: (context, index) {
return Text(testList[index]);
}),
);
}
The blue color is the Card and inside it, it is a list of notes.
You can also use Container instead of Card.

I want to implement OTP verification screen without any package

I want to implement OTP verification screen without any package.
when i entered the number it should move to next input field
I m using this code in my current project take a refrence this will help
class Otp extends StatefulWidget {
final String? phnNumber;
final String ? code;
String? from;
Otp({Key ?key, this.phnNumber, this.from, this.code}) : super(key:
key);
#override
_OtpState createState() => _OtpState();
}
class _OtpState extends State<Otp> {
double ? height ;
double ? width;
TextEditingController ? contrller1;
TextEditingController ? contrller2;
TextEditingController ? contrller3;
TextEditingController ? contrller4;
SendOtpRequest resend = SendOtpRequest();
SharedPreferences ? prefs;
getSharedPreferences () async
{
prefs = await SharedPreferences.getInstance();
}
String Code = "";
#override
void initState() {
// TODO: implement initState
super.initState();
contrller1 = TextEditingController();
contrller2 = TextEditingController();
contrller3 = TextEditingController();
contrller4 = TextEditingController();
getSharedPreferences();
}
#override
Widget build(BuildContext context) {
height= MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.height;
final verifyprovider = Provider.of<PostDataProvider>(context);
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight:height! * 0.07802345,
titleSpacing: 0,
backgroundColor: HexColor("#18263d"),
automaticallyImplyLeading: false,
leading: Padding(
padding: const EdgeInsets.only(left: 8.0,),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
color: Colors.transparent,
child: Image.asset("assets/images/back_ic-1.png")),
),
),
// SizedBox(width: width!*0.001234,),
title:Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: height!/15,
width: height!/15,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 2,
color:HexColor("#fc4f00"),
)),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
height: height!/11,
width: height!/11,
decoration: BoxDecoration(
image: const DecorationImage(
image:
AssetImage("assets/images/home_logo.png"),
fit: BoxFit.fill
),
shape: BoxShape.circle,
border: Border.all(
width: 1,
color:HexColor("#fc4f00"),
)),
),
),
),
SizedBox(width: width! * 0.04234,),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text("Verification",
style: GoogleFonts.oswald(fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: width! * 0.03345
),),
),
],
) ,
),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 32),
child: Column(
children: [
Text("We have send verification code on your mobile number",
style: GoogleFonts.oswald(fontStyle: FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#8b8b8b")),
),
SizedBox(height: height!/38,),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(first: true, last: false,controllerr:
contrller1),
_textFieldOTP(first: false, last: false,controllerr:
contrller2),
_textFieldOTP(first: false, last: false,controllerr:
contrller3),
_textFieldOTP(first: false, last: true, controllerr:
contrller4),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap:() {
resend.phoneNumber= widget.phnNumber;
resend.countryCode = widget.code;
verifyprovider.resendOtp(context,
jsonEncode(resend));
},
child: Text("Resend OTP?",
style: GoogleFonts.oswald(fontStyle:
FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#fc4f00")),
),
),
),
SizedBox(height: height!/28,),
GestureDetector(
onTap: (){
if(contrller1!.text.isNotEmpty&&
contrller2!.text.isNotEmpty&&contrller3!.
text.isNotEmpty&&contrller4!.text.isNotEmpty){
verifyOtpRequest verify = verifyOtpRequest();
verify.phoneNumber = widget.phnNumber;
verify.otp=
contrller1!.text+contrller2!.
text+contrller3!.text+contrller4!.text;
verifyprovider.otpVerification(context,
jsonEncode(verify), widget.from);
}else{
CommonUtils.showToast(msg: "Please fill all the
fields ");
}
},
child: Container(
height: height!/18,
width: width,
decoration: BoxDecoration(
color: HexColor("#fc4f00"),
borderRadius: BorderRadius.circular(10)
),
child: Center(
child: Text("Verify",style: TextStyle(
color: Colors.white,
fontSize: width!*0.02345
),),
)
),
),
],
),
],
),
),
),
);
}
Widget _textFieldOTP({bool ? first, last,
TextEditingController ?
controllerr}) {
return Container(
height:height!/12 ,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
controller: controllerr,
autofocus: true,
onChanged: (value) {
if (value.length == 1 && last == false) {
FocusScope.of(context).nextFocus();
}
if (value.length == 0 && first == false) {
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
),
),
),
);
}
}
When the length of the input data reaches one, you will have to change the text field focus node.
For Example
If you are in the first field, and you enter a number field one focus should be lost, and field two should be in focus. This can be done, by requestFocus.
This article will of help for you: Flutter Focus

Tab Bar in Flutter

I want to implement Tab Bar in my application having length 2 named "Need Help" and "Help Requests". In "Need Help" tab, I want my first container (i.e. Upload data to Firestore Database) and in "Help Requests" tab, I want my second container (i.e. Retrieve data from Firestore Database). I am new to flutter and will be very much grateful to you if you can help me.
Source code:
import 'package:chat_app/group_chats/group_info.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../constants.dart';
import '../global_data.dart';
class FinancialRoom extends StatelessWidget {
final String groupChatId, groupName;
FinancialRoom({required this.groupName, required this.groupChatId, Key? key})
: super(key: key);
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
TextEditingController amountValue = TextEditingController();
void onSend() async {
Map<String, dynamic> data = {
"amount": amountValue.text,
"sendBy": _auth.currentUser!.displayName,
"type": "text",
"time": FieldValue.serverTimestamp(),
};
amountValue.clear();
await _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.add(data);
}
#override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(groupName),
actions: [
IconButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => GroupInfo(
groupName: groupName,
groupId: groupChatId,
),
),
),
icon: Icon(Icons.more_vert)),
],
),
body: SafeArea(
child: ListView(padding: EdgeInsets.all(20.0), children: [
Container(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10.0,
),
TextFormField(
controller: amountValue,
decoration: InputDecoration(
hintText: 'Enter the amount you want',
labelText: 'Enter the amount you want',
prefixIcon: Icon(Icons.account_balance_wallet_outlined),
enabledBorder: kEnabledBorder,
focusedBorder: kFocusedBorder,
errorBorder: kErrorBorder,
focusedErrorBorder: kErrorBorder,
),
onTap: () {
},
// The validator receives the text that the user has entered.
validator: (value) {
if (value!.isEmpty) {
return 'Please enter the amount you want';
}
return null;
},
),
SizedBox(
height: kInputSpacing,
),
SizedBox(
width: double.infinity,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.blue,
textColor: Colors.white,
padding: EdgeInsets.only(top: 16.0, bottom: 16.0),
onPressed: onSend,
child: Text(
'SEND',
style: kButtonTextStyle,
),
),
),
],
),
),
Container(
height: size.height / 1.27,
width: size.width,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.orderBy('time')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
Map<String, dynamic> data =
snapshot.data!.docs[index].data()
as Map<String, dynamic>;
return messageTile(size, data);
},
);
} else {
return Container();
}
},
),
),
]),
),
);
}
Widget messageTile(Size size, Map<String, dynamic> data) {
return Builder(builder: (_) {
if (data['type'] == "text") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.blue,
),
child: Column(
children: [
Text(
data['sendBy'],
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
SizedBox(
height: size.height / 200,
),
Text(
data['amount'],
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
],
)),
);
} else if (data['type'] == "img") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
height: size.height / 2,
child: Image.network(
data['amount'],
),
),
);
} else if (data['type'] == "notify") {
return Container(
width: size.width,
alignment: Alignment.center,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.black38,
),
child: Text(
data['message'],
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
);
} else {
return SizedBox();
}
});
}
}
It's very straightforward to implement a simple TabBar in your app. All you need is a TabController and two widgets called TabBar and TabBarView. Here is a simple example:
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
]),
),
body: TabBarView(children: [
// Tab 1
Container(color: Colors.red),
// Tab 2
Container(color: Colors.blue),
]),
),
);
Now all you need to do is to replace children inside TabBarView with whatever you want to display.