How to get present number of inserts/widgets in an overlay? - flutter

I have created flat buttons that hide or show widget by inserting and removing widget in overlay.
And if I keep pressing the hide button even after there are no more widgets left in overlay, I get
'_overlay != null': is not true.
Now, I wish to add a check in there but I didn't find any way to check present number of widgets in Overlay stack.
Any help?
void showOverlayEntry() {
createOverlayEntry();
Overlay.of(context).insert(overlayEntry);
}
void removeOverlayEntry() {
//wish to add a check here if there are no more inserts left to remove
overlayEntry.remove();
}

Related

I want to make my Icons Automatically go to next Row in flutter if previous row gets completrly filled with icons

I am building a quiz app using Dart flutter in that some questions will get displayed and users have to click on true or false buttons depending upon question is right or wrong. To tell users that they are right or wrong icon (✓ or ✘) will get displayed in bottom row every time they choose answer by clicking on either of the button. But in flutter if row gets completely filled i got error
value: Not in inclusive range. So i want that icon should automatically go to next row.
Heres the short code which i tried:
List scorekeeper = [];
void score(bool userpickedanswer) {
setState((){
if (userpickedanswer == correctanswer) {
scorekeeper.add(Icon(Icons.check, color: Colors.green,));
}
else {
scorekeeper.add(Icon(Icons.close, color: Colors.red,));
}
}
Row {
childeren : scorekeeper
You can use the Wrap widget instead of the Row widget and when the line of icon fills to the end the Wrap widget makes another line automatically
Use the code like this:
Wrap(
children: scorekeeper,
),
You can use a wrap instead of a row. It prevents overflow by displaying the items depending on the available space:
https://api.flutter.dev/flutter/widgets/Wrap-class.html

How to close all overlays in flutter

I have built a screen that builds an overlay which contains a search bar widget.
Because I've built the overlay call in one class which then loads a separate widget class containing the search bar. I can't workout how to close the overlay from the active search bar class.
I have tried creating a close or dispose function but this only works when called from the parent class that initiated the overlay and not the child class containing the search widget.
Is there a close or kill all overlay function that I can use in this situation?
Or a way of calling the dispose / close overlay function that resides in the parent class from the child class when the search widget is running?
The only work-around I can think of is to rebuild the overlay and the search bar functionality into a single class which seems wrong.
I had the same issue and here is my solution. I call the close function prior to opening a new overlay:
// OVERLAYS
OverlayEntry? overlayWidget;
void closeOverlay() {
if ( overlayWidget == null || overlayWidget?.mounted == false) return;
overlayWidget?.remove();
overlayWidget = null;
}
void overlayWidgetDialog(BuildContext context, {required Widget child}) {
// avoid stacking
closeOverlay();
overlayWidget = OverlayEntry(
// maintainState: true,
// opaque: true,
builder: (context) {
return child;
});
Overlay.of(context)?.insert(overlayWidget!);
}
If you look at the code for Overlay you'll see this gem:
Do you see the highlighted part? Internally Flutter uses a private variable called "_entries" that has access to all overlays that are displayed at the moment.
However this is a private variable. So to answer your question, unless you keep a reference to all your overlay entries and then closing them manually, you cannot ask the system to do that for you.

How to tap all items of a list or a grid in a Flutter widget test?

In my Flutter widget tests I want to tap all (or first n) items in a list or grid view.
I already came up with a solution and although it seems to work, it looks overly complicated to find the tap target again by key:
for (final element in find.byType(ListTile).evaluate()) {
await tester.tap(find.byKey(element.widget.key!));
}
Is there a more elegant way to do it?
You can tap at a certain location on the widget:
e.g. tapping at center of the widget
for (final element in find.byType(ListTile).evaluate()) {
await tester.tapAt(tester.getCenter(find.byWidget(element.widget)));
}

How to add specific actions to ListView when user drags to its start or end (when the curvy blue lines appear)?

I'm curious is there an easy way to add such functionality to my Flutter ListViews?
For example, I would like to trigger some animation on another widget when the user drags "over the edge" on the ListView with all of it's items scrolled to the top or bottom, that is when the curvy blue line indicating that we're at the end of the list appears.
It obviously has an event firing up to show those lines anyway.
It's not hard actually, you can use a custom ScrollController with a listener:
declare it, then in initState put:
_myController = ScrollController();
_myController.addListener(_myScrollListener);
and the function itself can be something like this:
_myScrollListener(){
if (_myController.offset >= _controller.position.maxScrollExtent && !_myController.position.outOfRange) {
print("List end");
}
if (_myController.offset <= _controller.position.minScrollExtent && !_myController.position.outOfRange) {
print("List top");
}
Use the controller with your ListView, add what you need to the listener.

How to disable click events for entire children except one selected child in flutter?

Scenario: I have number of children in Listview.builder. For every children there is button which invokes TTS(text to speech). I wanted when any one of child is pressed rest all children should be in Listview.builder un-clickable till pressed child finishes its TTS.
I got answer from google like absorb pointer, ignore pointer to solve this.
But i dont know how to implement above scenario using these widgets.
Store a bool in the State of the class enclosing the ListView.builder. This bool should store if one of the children is currently doing its TTS. If it is true you should set all of the onPressed(or equivalent) method to null to prevent other taps from triggering an action. Ex:
bool hasBeenClicked = false;
void yourTTSMethod() {
setState(() {
hasBeenClicked = true;
});
... //Do normal method body
setState(() {
hasBeenClicked = true;
});
}
//In build method with each `List` item:
GestureDetector(//Just for sample, use whatever click detector you're currently using
onTap: hasBeenClicked ? null : yourTTSMethod
)