flutter_search_bar plugin onClose listener - dart

I am currently using flutter_search_bar plugin with a Tabbed Pages. Since my values change dynamically. I was wondering if there were any ways to add a listener to the package in order to make the necessary changes.
The plugin is here:
https://pub.dartlang.org/flutter/packages?q=flutter_search_bar&api=0
Update: this is what my code looks like now
_NavigationState() {
searchBar = new SearchBar(
controller: controller,
inBar: false,
setState: setState,
onSubmitted: onSubmit,
onChanged: onChange,
buildDefaultAppBar: buildAppBar,
hintText: 'Search Book',
closeOnSubmit: false,
clearOnSubmit: true,
onClosed: onClosed,
);
}
void onClosed() {
isSeaching = false;
loadTabpages();
setState(() {});
}

You can fork the repo and make the changes :
https://github.com/ArcticZeroo/flutter-search-bar/blob/master/lib/src/flutter_search_bar_base.dart
Add this var in SearchBar class:
/// Event triggered when the user close the search bar
final VoidCallback onClosed;
Add the field into the constructor
SearchBar(
{#required this.setState,
#required this.buildDefaultAppBar,
this.onSubmitted,
this.controller,
this.hintText = 'Search',
this.inBar = true,
this.colorBackButton = true,
this.closeOnSubmit = true,
this.clearOnSubmit = true,
this.showClearButton = true,
this.onChanged,
this.onClosed})
Line 144
Set a widget into the leading property
new IconButton(
icon: const BackButtonIcon(),
color: buttonColor,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () {
if (onClosed != null) {
onClosed();
}
Navigator.maybePop(context);
}),
Using the listener:
new SearchBar(
inBar: true,
setState: setState,
showClearButton: false,
clearOnSubmit: false,
closeOnSubmit: false,
onClosed: () {
}), ...
Updated handling the back button
return new AppBar(
leading: WillPopScope(
onWillPop: () {
if (onClosed != null) {
onClosed();
}
return Future.value(true);
},
child: new IconButton(
icon: const BackButtonIcon(),
color: buttonColor,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () {
if (onClosed != null) {
onClosed();
}
controller.clear();
Navigator.maybePop(context);
}),
),
....

Related

Page view controller attached to multiple scroll view

i have an issue with page view, it's working fine for first initialization (i mean when open the screen that contain page view from "Screen A" then go to open the "pageView screen" from other screen called "Screen B") in second time getting this issue
i think this issue happen because the controller re-intialiazed again, but i dispose the controller and make it equal to null when dispose screen
ScrollController attached to multiple scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
package:flutter/…/widgets/scroll_controller.dart:1
Failed assertion: line 109 pos 12: '_positions.length == 1'
Using provider to handle change in tabBar and Page View, the below code of provider class
class PageViewProvider extends BaseViewModel {
// Tabs Controller
int selectedTapIndex = 0;
PageController? pageViewController;
initPageIndex(int index) {
if (pageViewController != null) {
pageViewController = null;
}
print('init index $index');
selectedTapIndex = index;
pageViewController = PageController(initialPage: index, keepPage: false);
}
void changeSelectedTapIndex(int index) {
selectedTapIndex = index;
setState(ViewState.Idle);
}
void changePageView(int index) {
pageViewController!.jumpToPage(index);
}
}
this the tabed item widget with onTap Function to change index of TabBar
Consumer<PageViewProvider>(
builder: (context, pageViewProvider, _) => Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: [
Icon(
iconData,
color:
pageViewProvider.selectedTapIndex == selectedIndex
? purpleColor
: grey500,
),
normal14Text(
title,
color:
pageViewProvider.selectedTapIndex == selectedIndex
? purpleColor
: grey500,
),
],
),
).onTap(() {
pageViewProvider.changeSelectedTapIndex(selectedIndex!);
pageViewProvider.changePageView(selectedIndex!);
}));
at least, this is the pageView body
Consumer<PageViewProvider>(
builder: (context, pageViewProvider, _) => PageView(
controller: pageViewProvider.pageViewController,
onPageChanged: (index) {
pageViewProvider.changeSelectedTapIndex(index);
},
pageSnapping: true,
children: [
LeadProfileContent(),
LeadProfileTimeLine(),
LeadProfileCases(),
LeadProfileDeals(),
],
),
),
Thanks in advance.
It's solved. The issue here was with the Consumer above the page view body. Just removed it, and then accessed the pageViewController like this:
context.read<PageViewProvider>.pageViewController

Flutter bloc yield state is not received in listener

I add a event to bloc immediately after pop a CupertinoModalPopup. But yield a state and not received in bloc listener. The code is like below.There are more states and events, and it's all working, except this state is not received. I don't know why, maybe it's because I add the event after the showCupertinoModalPopup was pop. I am not sure. I didn't paste the whole codes here, I only kept the relevant code. I did set the breakpoint on yield ProfileUploadAvatarSucceed(user), and it stops here.
BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
return GestureDetector(
onTap: () async {
final file = await showCupertinoModalPopup(
context: context,
builder: (popupContent) {
return CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
child: Text('Photo Library'),
onPressed: () async {
final imageFile = await _picker.getImage(
source: ImageSource.gallery,
imageQuality: 70,
maxWidth: 480);
if (imageFile != null) {
Navigator.of(context).pop(imageFile);
}
},
),
],
);
});
BlocProvider.of<ProfileBloc>(context).add(UploadAvatarEvent(file));
};
},
listener: (_, state) {
if (state is ProfileLoadingState) {
BotToast.showLoading();
} else if (state is ProfileUploadAvatarSucceed) {
BotToast.closeAllLoading();
BotToast.showText(text: 'Avatar updated');
}
}
);
ProfileBloc.dart
#override
Stream<ProfileState> mapEventToState(
ProfileEvent event,
) async* {
if (event is UploadAvatarEvent) {
yield ProfileLoadingState();
await _apiProvider.updateUser(currentUser.id, payload);
final user = await _apiProvider.getUser(currentUser.id);
yield ProfileUploadAvatarSucceed(user);
}
}

Google Maps Flutter Custom marker not showing

Because I had problems with Google Maps and Bitmap descriptor, I tried to preload the icons before loading the Map, like this:
Widget preloadPinsAndLoadSearchMap() {
final config = ImageConfiguration(size: Size(48, 48));
final activePin = 'assets/active-pin.png';
final neutralPin = 'assets/neutral-pin.png';
final home = 'assets/home-map.png';
return FutureBuilder(
future: Future.wait([
BitmapDescriptor.fromAssetImage(config, activePin),
BitmapDescriptor.fromAssetImage(config, neutralPin),
BitmapDescriptor.fromAssetImage(config, home),
]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return SearchMap(pins: snapshot.data);
} else {
return Container();
}
},
);
}
And the SearchMap and the Markers:
// Each Marker is produced like this:
Marker createMarker(dynamic seller) {
return Marker(
markerId: MarkerId(seller.id),
position: LatLng(seller.latitude, seller.longitude),
onTap: () => onMarkerTap(seller),
// The icons are coming from the FutureBuilder.
icon: isActive ? activePin : neutralPin,
);
}
class SearchMap extends StatelessWidget {
Widget build(BuildContext context) {
final paris = initialPosition ??
LatLng(parisPosition.latitude, parisPosition.longitude);
return GoogleMap(
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
compassEnabled: false,
mapType: MapType.normal,
markers: markers,
initialCameraPosition: CameraPosition(target: paris, zoom: 15),
onMapCreated: onMapCreated,
onTap: (obj) => print(obj),
);
}
}
Happily it works on my devices very well, both iOS and Android. But on my reviewers devices, the icons are just not showing up. Is it a correct way to handle BitmapDescriptor? Maybe I’m wrong on the way to do this?

Way to change floating button icon when pressed

Is there any way to change the floating button's icon when pressed?
Code:
var musicButton = new FloatingActionButton(
onPressed: (){
if(playerState == PlayerState.playing) {
//setState(() => child = new Icon(Icons.pause));
setState((){
child: new Icon(Icons.play_arrow);
});
pause();
} else if (playerState == PlayerState.paused){
setState((){
child: new Icon(Icons.pause);
});
play();
}
},
tooltip: 'Play Music',
child: new Icon(Icons.pause));
You can just use a state variable to switch between icons.
Example:
bool playing = false;
then
var musicButton = new FloatingActionButton(
onPressed: (){
if(playerState == PlayerState.playing) {
setState((){
playing = false;
});
pause();
} else if (playerState == PlayerState.paused){
setState((){
playing = true;
});
play();
}
},
tooltip: 'Play Music',
child: playing?new Icon(Icons.pause):new Icon(Icons.play_arrow));
Hope that helped!
You can use enumeration also enum used to define named constant values.
enum Gender {Male,Female,} // enum definition globally
Gender selectedGender; // enum declaration
onPress: () {
setState(() {
selectedGender = Gender.Male;
});
},
Now you can use selectedGender Dart Conditional Operators ( ? : ) anywhere in your code.

Programmatically focusing on InputField and opening up keyboard

I have a situation where I need to programmatically focus on a InputField(such as in response to a button press).
I'm using the Focus.moveTo function; however, even though the InputField is focused (blinking cursor appears) the keyboard is not brought up.
It seems like the best solution would be to call the RequestKeyboard() function in _InputFieldState, but this is private.
What would be the best way to accomplish this?
Here is a code sample showing the workflow:
class InputFieldWrapper extends StatefulWidget {
#override
_InputFieldWrapperState createState() => new _InputFieldWrapperState();
}
class _InputFieldWrapperState extends State<InputFieldWrapper> {
InputValue _currentInput = new InputValue(text: 'hello');
// GlobalKey for the InputField so we can focus on it
GlobalKey<EditableTextState> _inputKey = new GlobalKey<EditableTextState>();
#override
Widget build(BuildContext context) {
return new Column(
children: [
// Button that should focus on the InputField when pressed
new IconButton(
icon: new Icon(Icons.message),
onPressed: () {
Focus.moveTo(_inputKey);
},
),
// InputField that should be focused when pressing the Button
new InputField(
value: _currentInput,
key: _inputKey,
onChanged: (InputValue input) {
setState(() {
_currentInput = input;
});
}
),
],
);
}
}
This was decided to be a bug and is being tracked at #7985.

Resources