Not getting values when querying list in search bar implementation Flutter - flutter

I need some help when implementing the search bar funcionality in Flutter.
I am implementing flappy_search_bar: https://pub.dev/packages/flappy_search_bar
However, it does return any value when I try to search something.
Is there anything I am missing? Seems trivial this kind of implementations, just query some list and include the results in other list but I cannot figure out the way to do it.
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
TextEditingController textController = TextEditingController();
Future<List<dynamic>> search(String search) async {
await Future.delayed(Duration(seconds: 2));
List<dynamic> dogs = BreedList.where((dog) => dog['breed'].contains(search)).toList();
return dogs;
// return List(search.length, (int index) {
// return DogClass(breed: "$search $index");
// });
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(children: [
Container(
margin: const EdgeInsets.only(top: 60, bottom: 15),
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Center(
child: Container(
width: MediaQuery.of(context).size.width -
(MediaQuery.of(context).size.width / 3.5),
height: 80,
child: SearchBar<dynamic>(
searchBarStyle: SearchBarStyle(borderRadius: BorderRadius.circular(20)),
onSearch: search,
cancellationWidget: Text('Cancel'),
emptyWidget: SizedBox.shrink(),
shrinkWrap:true,
onItemFound: (dynamic dogs, int index) {
return Container(
child: ListTile(
title: Text(dogs.breed.toString())
),
);
}),
//child: const Icon(Icons.search, color: Colors.white),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(Dimensions.radius20),
color: Colors.white),
),
)
],
),
),
//wrapping with this widgets the scroll problem is solved in list
const Expanded(
child: SingleChildScrollView(
child: BookPageBody(),
)),
]));
}
}

Related

Flutter - Row added -> change the text of a container

I'm quite inexperienced with flutter and have created this script.
When you tap on the red container you create a Row of buttons,
I would like when I click on a button in the Row -> the text of the blue container becomes the same as the text contained in the tapped button
Anyone know how I can do?
Thank you :)
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele!';
List<Container> OutputList = [];
void tool(String text) async {
List ListText = text.split(' ');
for (var i in ListText) {
OutputList.add(
Container(
child: GestureDetector(
onTap: () {},
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(i),
),
),
),
),
),
);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
tool(text);
print(OutputList);
});
},
child: Container(
width: 150.0,
height: 50.0,
color: Colors.red,
child: Center(child: Text('START ->')),
),
),
SizedBox(height: 50.0),
Row(
children: OutputList,
),
SizedBox(height: 50.0),
Container(
color: Colors.blue,
width: 200.0,
height: 50.0,
child: Text(''),
),
],
),
),
);
}
}
Yes you can add a few line of code check here i try to solve.
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele!';
//step 1 create variable
String newGeneratedText = "";
List<Container> OutputList = [];
void tool(String text) async {
List ListText = text.split(' ');
for (var i in ListText) {
OutputList.add(
Container(
child: GestureDetector(
onTap: () {
//add logic here to concatinate values
setState(() {
newGeneratedText = newGeneratedText + " " + i;//added " " for one space
});
},
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(i),
),
),
),
),
),
);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
tool(text);
print(OutputList);
});
},
child: Container(
width: 150.0,
height: 50.0,
color: Colors.red,
child: Center(child: Text('START ->')),
),
),
SizedBox(height: 50.0),
Wrap( // added for fixing more values and solve overflow exceptions error
children: OutputList,
),
SizedBox(height: 50.0),
Container(
color: Colors.blue,
width: 200.0,
height: 50.0,
child: Text(newGeneratedText), //final print values
),
],
),
),
);
}
}

How show a SizeTransition widget over parent widget (not expand it)

I am looking to create a DropDownMenu on Flutter for a form.
This DropDown menu is not pasted/collapse to the value selector.
So I implemented an Expand List View that comes just below the Row.
I want my SizedTransition widget to go over the parent widget and not shift the display. Is this possible? How do I do this?
I have :
Column [
InkWell,
SizeTransition -> ListView
]
I would like my SizeTransition should display over parent widget (not expand it).
There is my widget code app_drop_down_form.dart :
This widget take a list to item to display in expanded list and a default title when nothing is selected.
class AppDropDownForm extends StatefulWidget {
const AppDropDownForm({
required this.defaultTitle,
required this.dropList,
Key? key,
}) : super(key: key);
final String defaultTitle;
final List<AppDropDownItem> dropList;
#override
_AppDropDownFormState createState() => _AppDropDownFormState();
}
class _AppDropDownFormState extends State<AppDropDownForm>
with SingleTickerProviderStateMixin {
bool enableList = false;
int? _selectedIndex;
late AnimationController _expandController;
late Animation<double> _expandAnimation;
#override
void initState() {
_expandController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300));
_expandAnimation =
CurvedAnimation(parent: _expandController, curve: Curves.easeInCubic);
super.initState();
}
#override
void dispose() {
_expandController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Container selectedItemWidget = _buildHeaderForm();
return Column(children: <Widget>[
InkWell(
onTap: _performExpand,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: AppTheme.lightGrey, width: 1),
borderRadius: enableList
? const BorderRadius.vertical(top: Radius.circular(10))
: const BorderRadius.all(Radius.circular(10)),
color: Colors.white),
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(child: selectedItemWidget),
const Icon(Icons.expand_more,
size: 24.0, color: AppTheme.thirdColor)
]))),
SizeTransition(
sizeFactor: _expandAnimation, child: _buildExpandableSelectableList())
]);
}
Container _buildHeaderForm() {
if (_selectedIndex == null) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 15),
child:
Text(widget.defaultTitle, style: AppTheme.dropDownHintTextStyle));
} else {
var selectItem = widget.dropList
.where((element) => element.index == _selectedIndex)
.first;
return Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(children: [
SizedBox(
height: 25,
width: 25,
child: SvgPicture.asset(selectItem.iconPath,
color: AppTheme.black)),
const SizedBox(width: 20),
Text(selectItem.name, style: AppTheme.dropDownSelectedTextStyle)
]));
}
}
Widget _buildExpandableSelectableList() {
return Container(
decoration: BoxDecoration(
border: Border.all(color: AppTheme.lightGrey, width: 1),
borderRadius:
const BorderRadius.vertical(bottom: Radius.circular(10)),
color: AppTheme.thirdColor),
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
itemCount: widget.dropList.length,
itemBuilder: (context, position) {
return _buildExpandableItem(position);
}));
}
InkWell _buildExpandableItem(int position) {
var item =
widget.dropList.where((element) => element.index == position).first;
return InkWell(
onTap: () {
_onChanged(position);
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(children: [
SizedBox(
height: 25,
width: 25,
child:
SvgPicture.asset(item.iconPath, color: AppTheme.white)),
const SizedBox(width: 20),
Text(item.name, style: AppTheme.dropDownLightTextStyle)
])));
}
void _onChanged(int position) {
setState(() {
_selectedIndex = position;
_performExpand();
});
}
void _performExpand() {
enableList = !enableList;
if (enableList) {
_expandController.forward();
} else {
_expandController.reverse();
}
}
}
````

How can I send data from bottom sheet to parent widget?

I have list of products in bottom sheet, when I choose any product I want to parent's widget to add it, unfortunately my product adds only after hot reload, or when I create a new route from bottom sheet to parent's widget, how can I solve this problem, any ideas? Here is the part of the bottom sheet code
class IceBottomSheet extends StatefulWidget {
const IceBottomSheet({Key? key}) : super(key: key);
#override
_IceBottomSheetState createState() => _IceBottomSheetState();
}
class _IceBottomSheetState extends State<IceBottomSheet> {
final _model = ProductWidgetsModel();
#override
Widget build(BuildContext context) {
List<Widget> productWidgetList = [];
products.forEach((product) =>
productWidgetList.add(SingleProductWidget(product: product)));
return Provider(
model: _model,
child: Expanded(
child: GridView.count(
crossAxisSpacing: 10,
mainAxisSpacing: 16,
shrinkWrap: true,
crossAxisCount: 2, children: productWidgetList),
),
);
}
}
class SingleProductWidget extends StatefulWidget {
final Product product;
const SingleProductWidget({Key? key, required this.product})
: super(key: key);
#override
State<SingleProductWidget> createState() => _SingleProductWidgetState();
}
class _SingleProductWidgetState extends State<SingleProductWidget> {
#override
Widget build(BuildContext context) {
final model = Provider.of(context)?.model;
return Padding(
padding: const EdgeInsets.all(5.0),
child:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: double.infinity,
height: 100,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: widget.product.image,
),
shape: BoxShape.circle,
border: Border.all(
color: model?.idSelected == widget.product.id
? Colors.yellow
: Colors.grey,
width: 5.0,
style: BorderStyle.solid,
),
),
child: GestureDetector(
onTap: () {
model?.idSelected = widget.product.id;
// Route route =
// MaterialPageRoute(builder: (context) => BerryPage(context,));
// Navigator.push(context, route);
if(model?.idSelected == 1){
menuRow.removeAt(2);
Navigator.pop(context);
choice.insert(2, Adds(id: 102, name: 'Холодок', img: 'https://autogear.ru/misc/i/gallery/73434/2759438.jpg'));
}
}),
),
),
And here is the part of parent's widget code, it is inside GestureDetector
else if (index == 2){
setState(() {
});
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext builder) {
return Container(
height: 250,
child: Column(
children: [
SizedBox(
height: 10,
),Row(
children: [
Padding(
padding: EdgeInsets.only(left: MediaQuery.of(context).size.width*0.25 + MediaQuery.of(context).size.width *0.12),
child: Text(
'Холодок',
style: TextStyle(
fontFamily: 'Newfont',
fontSize: 22,
),
),
),
SizedBox(width: MediaQuery.of(context).size.width*0.25,),
IconButton(icon: Icon(Icons.close),onPressed: (){Navigator.pop(context);},)
],
),
Divider(),
IceBottomSheet(),
],
));
},
);
So when you open the BottomSheet you have to add await before it, so when you call Navigator.pop(context, data_you_want_to_pass_to_parent) it will wait for some data to be returned.
final data = await openBottomSheet();
inside the bottomSheet when you want to close, just pass the the desired data as so
Navigator.pop(context, data_you_want_to_pass_to_parent);

Keyboard automatically disappears from TextField in ListView.Builder

I'm trying to implement a solution where a row (containing both a TextField and a Text) in ListView.Builder is automatically for every record retrieved from a webserver.
However when I want to start typing in such a TextField the keyboard appears and immediatly disappears again.
This is the code of my screen.
class GameScreen extends StatelessWidget {
static const RouteName = "/GameScreen";
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
const horizontalMargin = 20.0;
return Scaffold(
appBar: getAppBar(),
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
Background(),
Column(
children: <Widget>[
Header("Starting letter: B"),
Expanded(
child: ListBlocProvider(
listWidget: GameCategoriesList(),
itemsService: CategoriesService(),
margin: EdgeInsets.only(
left: horizontalMargin,
bottom: 10,
right: horizontalMargin,
),
),
),
SizedBox(
height: 20,
),
SizedBox(
width: size.width - 40,
height: 60,
child: Container(
height: 60,
child: TextButtonWidget(
() {
// Navigator.of(context).pushNamed(GameScreen.RouteName);
},
"Stop game",
),
),
),
SizedBox(
height: 20,
)
],
),
],
),
);
}
}
This is the code of my ListBlocProvider:
class ListBlocProvider extends StatelessWidget {
final ListWidget listWidget;
final ItemsService itemsService;
final bool useColor;
final bool usePaddingTop;
final double height;
final EdgeInsets margin;
const ListBlocProvider({
#required this.listWidget,
#required this.itemsService,
this.useColor = true,
this.usePaddingTop = true,
this.height = 200,
this.margin,
});
#override
Widget build(BuildContext context) {
const horizontalMargin = 20.0;
return BlocProvider(
create: (context) => ItemsBloc(itemsService: itemsService)..add(ItemsFetched()),
child: Container(
padding: usePaddingTop ? EdgeInsets.only(top: 10) : null,
decoration: BoxDecoration(
color: this.useColor ? Color.fromRGBO(10, 50, 75, 0.9) : null,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
margin: this.margin,
height: this.height,
child: this.listWidget,
),
);
}
}
This is the code of my List:
class GameCategoriesList extends ListWidget {
#override
_GameCategoriesListState createState() => _GameCategoriesListState();
}
class _GameCategoriesListState extends State<GameCategoriesList> {
#override
Widget build(BuildContext context) {
return BlocBuilder<ItemsBloc, ItemsState>(
builder: (context, state) {
if (state is ItemsFailure) {
return Center(
child: Text('failed to fetch categories'),
);
}
if (state is ItemsSuccess) {
if (state.items.isEmpty) {
return Center(
child: Text('no categories found.'),
);
}
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
var textEditingController = TextEditingController();
return GameCategoryItemWidget(
key: UniqueKey(),
categoryModel: state.items[index],
textEditingController: textEditingController,
);
},
itemCount: state.items.length,
);
}
return Center(
child: LoadingIndicator(),
);
},
);
}
}
And this is the code where the both the TextField and the Text are build:
class GameCategoryItemWidget extends StatefulWidget {
final CategoryModel categoryModel;
final TextEditingController textEditingController;
const GameCategoryItemWidget({Key key, this.categoryModel, this.textEditingController}) :
super(key: key);
#override
_GameCategoryItemWidgetState createState() => _GameCategoryItemWidgetState();
}
class _GameCategoryItemWidgetState extends State<GameCategoryItemWidget> {
var formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Container(
child: Form(
key: this.formKey,
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10, top: 20, bottom: 10),
child: Text(
this.widget.categoryModel.name,
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
),
Container(
color: Colors.white,
child: InputField(
InputDecoration(labelText: this.widget.categoryModel.name),
this.widget.textEditingController,
false,
),
),
],
),
),
);
}
#override
void dispose() {
this.widget.textEditingController.dispose();
super.dispose();
}
}
The InputField is a custom widget to hide the switch between a Material and a Cupertino version of the TextField.
I've already tried to remove the Key from the custom TextField widget. The funny part is that the input is actually working, however it can't determine for which of the TextFields in the ListView the input is determined so it adds the input to all of them. I've also tried to swap things around with making Stateless widgets Statefull, but that didn't help either.
The entire build is based upon: https://bloclibrary.dev/#/flutterinfinitelisttutorial.
Hoping you guys can help me.

Access variable built in different file/class

I have file.a which contains an array:
final _likes = <String>[];
Based on answers selected by the user, items are added to this array.
I want to then be able to, at the press of a button, display the items in the array to the user.
The issue is that the button I want the users to press is defined in file.b (as the Icon is on the AppBar).
How can I give file.b the ability to see the variable _likes and access the data in it, when it lives in file.a?
file.a:
import 'package:flutter/material.dart';
import './main.dart';
class Images extends StatefulWidget {
#override
_ImagesState createState() => _ImagesState();
}
class _ImagesState extends State<Images> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
#override
// ignore: must_call_super
void initState() {
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
);
_animation = Tween(
begin: 0.0,
end: 1.0,
).animate(_controller);
}
#override
dispose() {
_controller.dispose();
super.dispose();
}
int index = 0;
final likes = <String>[];
#override
Widget build(BuildContext context) {
_controller.forward();
return GestureDetector(
onHorizontalDragEnd: (DragEndDetails dragEndDetails) {
if (dragEndDetails.primaryVelocity == 0) return;
if (dragEndDetails.primaryVelocity.compareTo(0) == -1)
setState(() {
_controller.reset();
dateIdeas.removeAt(index);
});
else
setState(() {
_controller.reset();
likes.add(dateIdeas[index]['Description']);
dateIdeas.removeAt(index);
});
},
child: new Column(
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: FadeTransition(
opacity: _animation,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.pink[200],
width: 7,
),
borderRadius: BorderRadius.circular(9),
),
child: new Container(
child: new Image.asset(dateIdeas[index]['Image']),
),
),
),
),
Container(
alignment: Alignment.topCenter,
child: Text(dateIdeas[index]['Description'],
style: TextStyle(
fontSize: 30,
color: Colors.black,
fontFamily: 'IndieFlower',
)),
),
],
),
],
)
],
),
);
}
}
file.b:
import 'package:flutter/material.dart';
import './surprises.dart';
import './images.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SO Surprises',
theme: ThemeData(
primaryColor: Colors.pink[200],
),
home: MyHomePage(title: ''),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
{
int ideaCount = 1;
int _swipeCount = 0;
void _swipe() {
setState(() {
_swipeCount++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
Container(
height: 150,
width: 150,
child: IconButton(
icon: Image.asset('assets/images/SO.png'),
padding:
const EdgeInsets.only(right: 40.0, top: 10, bottom: 10.0),
),
),
GestureDetector(
onTap: () => print(Images.likes),
child: Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Icon(
Icons.star,
color: Colors.white,// add custom icons also
),
),
),
],
),
body: _swipeCount == 0
? Stack(
children: <Widget>[
GestureDetector(
onHorizontalDragEnd: (DragEndDetails dragEndDetails) {
if(dragEndDetails.primaryVelocity == 0) return;
_swipe();
},
child: Container(
color: Colors.transparent,
alignment: Alignment.center,
child: Text("Swipe to get started! $_swipeCount"),
),
),
],
)
: Template(),
);
}
}
By prefixing your likes list with an underscore (_), it means you are making that method only accessible inside the class it belongs too.
To be able to use the method in other parts of your program, remove the underscore(_).
After removing the _, you are making the likes list accessible from other parts of your code.