How to reload screen on future data - android

I have TabBarView with six tabs.
I'm trying to show all the installed apps in first tab.
Even after apps is filled CircularProgressIndicator is displayed. Apps are listed once the first tab is revisited.
AppScreenC is called for first tab.
final model = AppModel();
class AppScreenC extends StatefulWidget {
#override
_AppScreenCState createState() => _AppScreenCState();
}
class _AppScreenCState extends State<AppScreenC> {
List<Application> apps = model.loadedApps();
#override
Widget build(BuildContext context) => _buildApps();
Widget _buildApps() => apps != null
? ListView.builder(
itemCount: apps.length,
itemBuilder: (BuildContext context, int index) =>
_buildRow(apps[index]))
: Center(child: CircularProgressIndicator());
Widget _buildRow(ApplicationWithIcon app) {
final saved = model.getApps().contains(app.apkFilePath);
return ListTile(
leading: Image.memory(app.icon, height: 40),
trailing: saved
? Icon(Icons.check_circle, color: Colors.deepPurple[400])
: Icon(Icons.check_circle_outline),
title: Text(app.appName),
onTap: () => setState(() => saved
? model.removeApp(app.apkFilePath)
: model.addApp(app.apkFilePath)),
);
}
}
AppModel class has all the necessary methods.
class AppModel{
final _saved = Set<String>();
List<Application> apps;
AppModel() {
loadApps();
}
Set<String> getApps() {
return _saved;
}
addApp(String apkPath) {
_saved.add(apkPath);
}
removeApp(String apkPath) {
_saved.remove(apkPath);
}
loadApps() async {
apps = await DeviceApps.getInstalledApplications(
onlyAppsWithLaunchIntent: true,
includeSystemApps: true,
includeAppIcons: true);
apps.sort((a, b) => a.appName.compareTo(b.appName));
}
loadedApps() => apps;
}
This is happening because apps is null, when the screen was called first time. It loads the apps in background. Upon visiting the screen again, apps are displayed.
Any help is welcome

What you can do is calling setState() after your Function is done. You need to change loadedApp to return a Future:
class AppScreenC extends StatefulWidget {
#override
_AppScreenCState createState() => _AppScreenCState();
}
class _AppScreenCState extends State<AppScreenC> {
#override
void initState(){
super.initState();
model.loadApps().then((loadedApps){ //loadApps() will return apps and you don't need loadedApps() method anymore
setState((){ //rebuilds the screen
apps = loadedApps
})});
}
#override
Widget build(BuildContext context) => _buildApps();
Widget _buildApps() => apps != null
? ListView.builder(
itemCount: apps.length,
itemBuilder: (BuildContext context, int index) =>
_buildRow(apps[index]))
: Center(child: CircularProgressIndicator());
Widget _buildRow(ApplicationWithIcon app) {
final saved = model.getApps().contains(app.apkFilePath);
return ListTile(
leading: Image.memory(app.icon, height: 40),
trailing: saved
? Icon(Icons.check_circle, color: Colors.deepPurple[400])
: Icon(Icons.check_circle_outline),
title: Text(app.appName),
onTap: () => setState(() => saved
? model.removeApp(app.apkFilePath)
: model.addApp(app.apkFilePath)),
);
}
}
And your AppModel will look like this:
class AppModel{
final _saved = Set<String>();
List<Application> apps;
AppModel() {
loadApps();
}
Set<String> getApps() {
return _saved;
}
addApp(String apkPath) {
_saved.add(apkPath);
}
removeApp(String apkPath) {
_saved.remove(apkPath);
}
Future loadApps() async {
apps = await DeviceApps.getInstalledApplications(
onlyAppsWithLaunchIntent: true,
includeSystemApps: true,
includeAppIcons: true);
apps.sort((a, b) => a.appName.compareTo(b.appName));
return Future.value(apps);
}
}
You can also use FutureBuilder as suggested in the comments

Related

Sending data to other page with bloc cubit

My problem is this. I created cubit for 2 different pages. When I am on the first page, I can fill the list inside the 2nd page and I can read it from the log. However, when I go to the second page, the list I filled in from the previous page is still empty.
Main.dart
home:
MultiBlocProvider(
providers: [
BlocProvider(create: (_) => HomeCubit(PhotoService())),
BlocProvider(create: (_)=> FavoritesCubit())//Gerekiyor,homeviewda içerisindeki methoda erişmem gerekiyor
],
child: const HomeView())
HomeView.dart
where I run the function in favoritescubit and add it to the list
onTap: () {
BlocProvider.of<FavoritesCubit>(context).addFavorite(
context,
state.selectItem![index],
);
print(state.selectItem?[index].isSelected);
context.read<FavoritesCubit>().getAllFavorites();
// print("UI --- ${state.selectItem![index].isSelected}");
// context.read<FavoriteBloc>().add(
// AddFavorite(photoList, photoList.isSelected));
// print(" ispressed ${photoList.isSelected}");
},
FavoritesCubit.dart
class FavoritesCubit extends Cubit<FavoritesState> {
FavoritesCubit() : super(const FavoritesState());
final List<PhotoModel> favoriteList = <PhotoModel>[];
Future<void> getAllFavorites() async {
print("FavoriteList : ${favoriteList.length}");
emit(state.copyWith(favoriteList: favoriteList));
}
Future<void> addFavorite(
BuildContext context,
PhotoModel photo,
) async {
photo.isSelected = !photo.isSelected;
if (favoriteList.contains(photo) == false) {
favoriteList.add(photo);
emit(state.copyWith(
favoriteList: favoriteList, isFavorite: photo.isSelected));
print("${state.favoriteList!.length}asdasd");
} else if (favoriteList.contains(photo) == true) {
favoriteList.remove(photo);
emit(state.copyWith(
favoriteList: favoriteList, isFavorite: photo.isSelected));
print("${state.favoriteList!.length}asdasd");
}
FavoriteView.dart
class FavoriteView extends StatefulWidget {
const FavoriteView({Key? key}) : super(key: key);
#override
State<FavoriteView> createState() => _FavoriteViewState();
}
class _FavoriteViewState extends State<FavoriteView> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => FavoritesCubit()..getAllFavorites(),
child: Scaffold(
appBar: AppBar(
title: const Text("Bloc Example"),
),
body: buildFavoriteList(context),
),
);
}
}
Widget buildFavoriteList(BuildContext context) {
return BlocConsumer<FavoritesCubit, FavoritesState>(
listener: (context, state) {
// TODO: implement listener
},
builder: (context, state) {
return ListView.builder(
itemCount: state.favoriteList?.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: (() {
// navigateToPostDetailPage(context, photos[index]);
}),
child: Padding(
padding: const EdgeInsets.all(10),
child: PhotoListTile(
isPressed: state.favoriteList![index].isSelected,
imageUrl: state.favoriteList![index].thumbnailUrl.toString(),
title: state.favoriteList![index].title.toString(),
url: state.favoriteList![index].url.toString(),
onTap: () {
// context.read<HomeCubit>().addFavorite(
// context,
// state.favoriteList![index],
// state.favoriteList![index].isSelected);
// context
// .read<FavoriteBloc>()
// .add(RemoveFavorite(photos[index]));
},
),
),
);
});
},
);
Okey, now with your added information about your FavoriteView it is clear what the problem is.
In your FavoriteView you create a new cubit, which is not the same as you created in the MultiBlocProvider. That is why it is always empty on your FavoriteView
create: (context) => FavoritesCubit()..getAllFavorites(), // This is the issue
Make sure that your FavoriteView is a child somewhere under your MultiBlocProvider and remove the creation of a new FavoritesCubit in that view. I.e. remove the BlocProvider in your FavoriteView

Flutter - setState to another class

I just started programming in Flutter. I want to create an app to keep track of the expiration dates of food.
My app is composed of:
main.dart that returns a MaterialApp class with inside the Home
home.dart that contains the AppBar, a Scaffold which contains a ListBuilder() as body and a FAB which should add a new item.
list_builder.dart that contains the stateful widget ListBuilder which takes a list of Strings from items_list.dart and creates a ListView with some tiles
items_list.dart that contains a List of Strings, a function to remove, add and retrieve the list.
What I made so far is a list of items with a trailing trash icon button that deletes the single item from the list. All works as expected.
Now I want that pressing the FAB, it triggers the ItemsList.addItem() which adds an item to the list. That works, of course, but the list on screen (created by the list_builder.dart) is not updated unless I delete one item.
I tried unsuccessfully to use callback functions, I'm sure I'm missing something.
This is the code:
main.dart
import 'package:flutter/material.dart';
import 'home.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Quando Scade?',
home: Home(),
theme: ThemeData(
primarySwatch: Colors.lightGreen,
),
);
}
}
home.dart
import 'package:flutter/material.dart';
import 'package:quando_scade/items_list.dart';
import 'list_builder.dart';
class Home extends StatelessWidget {
const Home({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Quando Scade?'),
backgroundColor: Theme.of(context).colorScheme.primary,
),
body: ListBuilder(),
floatingActionButton: FloatingActionButton(
onPressed: () {
ItemsList.addItem('ciao');
print('item added!!!');
},
child: const Icon(Icons.add),
),
);
}
}
list_builder.dart
import 'package:flutter/material.dart';
import 'items_list.dart';
class ListBuilder extends StatefulWidget {
const ListBuilder({Key key}) : super(key: key);
#override
_ListBuilderState createState() => _ListBuilderState();
}
class _ListBuilderState extends State<ListBuilder> {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: ItemsList.getItems().length,
itemBuilder: (context, index) {
return _buildRow(ItemsList.getItems()[index], index);
},
);
}
Widget _buildRow(String item, int index) {
return ListTile(
title: Text(
item,
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
ItemsList.removeItem(index);
});
},
),
);
}
}
items_list.dart
class ItemsList {
static List<String> _items = [
'banane',
'latte',
'caffè',
'vino',
'sushi',
'birra',
];
// to add items
static void addItem(String name) => ItemsList._items.add(name);
// to remove item
static void removeItem(int i) => ItemsList._items.removeAt(i);
// returns the list of items
static List<String> getItems() {
return ItemsList._items;
}
}
I see you are using setState on item delete, you should use it when adding an item as well:
...
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
ItemsList.addItem('ciao');
});
print('item added!!!');
},
child: const Icon(Icons.add),
),
...
Of course, make the Home widget as StatefulWidget before that.
Though this is not an optimal solution to what you're looking for, however, it's better than changing your Home class to a stateful widget and rebuilding your entire widget tree. I have modified your code to make it work exactly the way you want it without calling the setState function.
home.dart
class Home extends StatelessWidget {
const Home({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Quando Scade?'),
backgroundColor: Theme.of(context).colorScheme.primary,
),
body: ListBuilder(),
floatingActionButton: FloatingActionButton(
onPressed: () {
ItemsList.itemList.addItem('ciao');
print('item added!!!');
},
child: const Icon(Icons.add),
),
);
}
}
items_list.dart
class ItemsList {
final _list = [
'banane',
'latte',
'caffè',
'vino',
'sushi',
'birra',
];
StreamController<List<String>> _items =
StreamController<List<String>>.broadcast();
Stream<List<String>> get items => _items.stream;
// to add items
void addItem(String name) {
//_reOpenStream();
_list.add(name);
_items.sink.add(_list);
// _items.close();
}
// to remove item
void removeItem(int i) {
//_reOpenStream();
_list.removeWhere((element) => element == _list[i]);
_items.sink.add(_list);
}
void close() {
_items.close();
}
static final ItemsList _singleton = ItemsList._internal();
static ItemsList get itemList => ItemsList();
factory ItemsList() {
return _singleton;
}
ItemsList._internal();
}
list_builder.dart
class ListBuilder extends StatefulWidget {
const ListBuilder({Key key}) : super(key: key);
#override
_ListBuilderState createState() => _ListBuilderState();
}
class _ListBuilderState extends State<ListBuilder> {
#override
Widget build(BuildContext context) {
return StreamBuilder<List<String>>(builder: (_, snapshot) {
int itemCount = snapshot.data.length;
return ListView.builder(
itemCount: itemCount,
itemBuilder: (context, index) {
//Handle the empty list by replacing the container widget with your logic
return itemCount <=0 ? Container(): _buildRow(snapshot.data[index], index);
},
);
}, initialData: [],);
}
Widget _buildRow(String item, int index) {
return ListTile(
title: Text(
item,
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
ItemsList.itemList.removeItem(index);
});
},
),
);
}
}
Only call the close() method when you no longer need the stream, otherwise, it'd throw a bad state error when you try accessing it again. Additionally, as you progress in your learning try refactoring your codes to use an architecture design.. Peace!

Checking one CheckBox in a ListView checks all of the rest using Flutter

I am completly new to Flutter and Stackoverflow. This is my first question to be in fact so please forgive me if I totaly fail at asking this question. I am trying to make a simple Flutter app that provides a ListView of questions and a checkbox beside each. The user can then choose which question they want to answer. My problem is that when the user checks any of the checkboxes then all get checked and vise versa. The questions themselves are retrieved from a backendless database. The code below is what i have so far. I would really appreciate any help anyone can provide me.
import 'package:flutter/material.dart';
class Questions extends StatefulWidget {
final List<Map> questionList;
Questions(this.questionList);
#override
_QuestionsState createState() => _QuestionsState();
}
class _QuestionsState extends State<Questions> {
bool _questionSelected = true;
Widget _buildQuestionItem(BuildContext context, int index) {
return ListTile(
title: Text(widget.questionList[index]['question']),
trailing: Checkbox(
value: _questionSelected,
onChanged: (bool val){
setState(() {
_questionSelected = val;
});
},
),
);
}
#override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.all(10),
itemBuilder: _buildQuestionItem,
itemCount: widget.questionList.length,
);
}
}
UPDATED:
Thankful for Mohammed Ashab Uddin suggestions I feel that I am close to getting this thing to work but I am still getting an error
"RangeError (index): Invalid value: Valid value range is empty: 0"
I think I should have posted the main.dart code where I set the value of the questionList perhaps it is an order of code execution that causes this error so please find my code for main.dart below in hopes it would help in figuring out this issue.
import 'package:flutter/material.dart';
import 'package:backendless_sdk/backendless_sdk.dart';
import 'package:flutter/rendering.dart';
import 'questions.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RT Database Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Questions'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
static const String API_HOST = "https://api.backendless.com";
static const String APP_ID = "<APP_ID>";
static const String ANDROID_APP_KEY = "<ANDROID_APP_KEY>";
static const String IOS_APP_KEY = "<IOS_APP_KEY>";
IDataStore<Map> questionsStore = Backendless.data.of('Questions');
List<Map> questionsList = [];
var _questionSelected = false;
#override
void initState() {
super.initState();
_initBackendless();
_enableRealTime();
getQuestions();
}
void _initBackendless() {
Backendless.setUrl(API_HOST);
Backendless.initApp(APP_ID, ANDROID_APP_KEY, IOS_APP_KEY);
}
void _enableRealTime() {
EventHandler<Map> rtHandlers = questionsStore.rt();
rtHandlers.addCreateListener((question) {
setState(() {
questionsList = List.from(questionsList);
questionsList.add(question);
});
});
rtHandlers.addUpdateListener((question) {
setState(() {
questionsList = List.from(questionsList
.map((m) => m['objectId'] == question['objectId'] ? question : m));
});
});
rtHandlers.addDeleteListener((question) {
setState(() {
questionsList = List.from(questionsList);
questionsList.removeWhere((m) => m['objectId'] == question['objectId']);
});
});
}
void _selectQuestion(bool newValue) {
setState(() {
_questionSelected = newValue;
});
}
void getQuestions() {
DataQueryBuilder queryBuilder = DataQueryBuilder()
..pageSize = 100
..sortBy = ['created'];
questionsStore
.find(queryBuilder)
.then((response) => setState(() => questionsList = response));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My Life History"),
),
body: FractionallySizedBox(
heightFactor: 0.5,
child: Questions(questionsList),
),
);
}
}
The variable _questionSelected is a global variable. All the checkbox widgets are using this variable as the value. Therefore, when the variable changes on the onChanged() function, all the values are also changed to the value of _questionSelected.
In this case, you need to keep track of all the values of the checkbox widget. So, you should use an array rather than a single variable.
What I usually do is, create a new list that will contain only the selected elements.
Remove an element if it is not selected and add an element if it is selected.
//generate a list of false values with the length of questionList
List<bool> _questionSelected;
initState(){
_questionSelected = List<bool>.filled(questionList.length, false, growable: true);
super.initState();
}
Widget _buildQuestionItem(BuildContext context, int index) {
return ListTile(
title: Text(widget.questionList[index]['question']),
trailing: Checkbox(
value: _questionSelected[index],
onChanged: (bool val){
setState(() {
_questionSelected[index] = val;
});
},
),
);
}

Flutter: Calling different pages deppending on the situation (logged or not logged user)

I'm having a problem with my app.
The situation is: i have a very simple login system on the app and i save the logged user using SharedPreferences.
But if the user leaves the app and then return it will open the login screen again, so i want to skip the login screen if the user is logged.
So in my main i put a function to check if there is login information, if yes it would redirect right to the app page or to the login page if not.
But when i try to call the app page it always calls the page setted on the Home part.
How can i solve this?
Is there any way to make it ignore the Home?
Is there a way to make the "if" part on the home? Would be the better solution but its not possible.
Also i know i'm not using the best way to make this control, but it works (despite of this problem i have now, sure) and if you have any tips on making it better i would appreciate.
Heres my code:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
void main() => runApp(new MyApp());
class _MyAppState extends State<MyApp> {
Future<void> verificaLogin() async {
print("running ok"); //just to test if the function runs
final prefs = await SharedPreferences.getInstance();
final key = 'usuario';
final value = prefs.getString(key);
print('saved tester $value');
String usu = value; /
if (usu.isEmpty) {
BuildContext context;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginScreen()), //sends to loginscreen if not logged
);
}
if (usu.isNotEmpty) {
BuildContext context;
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) => Pedidos())); //sends to main (not main.dart) app page
}
}
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => verificaLogin());
}
Widget build(BuildContext context) {
return BotToastInit(
child: MaterialApp(
navigatorObservers: [BotToastNavigatorObserver()],
title: "Test App",
theme: ThemeData(
primarySwatch: Colors.green,
),
debugShowCheckedModeBanner: false,
home: LoginScreen(), //i'm calling the loginscreen, it ignores the function on the top
),
);
}
}
Please make one SplashScreen like below it resolves your issue..
and call this as home: SplashScreen(),
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
String loginData = "";
SharedPreferences sharedPreferences;
void initState() {
super.initState();
readFromStorage();
}
void readFromStorage() async {
sharedPreferences = await SharedPreferences.getInstance();
final key = 'usuario';
loginData = sharedPreferences.getString(key);
if (loginData.isNotEmpty) {
Future.delayed(const Duration(milliseconds: 3000), () {
setState(() {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) => Pedidos()));
});
});
} else {
Future.delayed(const Duration(milliseconds: 3000), () {
setState(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),);
});
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(
size: 100.0,
),
],
)),
);
}
}
Hi you can use a FutureBuilder at vefiricaLoigin, and then Material App at home use verificaLogin,
https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
verificaLogin() {
return FutureBuilder<Widget>(
future: SharedPreferences.getInstance(),
builder: (BuildContext context, prefs) {
final key = 'usuario';
final value = prefs.getString(key);
String usu = value;
if (usu.isEmpty) {
return LoginScreen()l
} else {
return Pedidos();
}
);
}
Widget build(BuildContext context) {
return MaterialApp(
title: "Test App",
theme: ThemeData(
primarySwatch: Colors.green,
),
debugShowCheckedModeBanner: false,
home: verificaLogin()
);
}

Navigator.pop won't close the simpledialog in flutter

I'm building android app using flutter. I have a problem to close the simple dialog programmatically.
Now I have a stateful page named ListVessel. This page contains listTile from array otherVessels.
Below is the code for this page.
class ListVessel extends StatefulWidget {
final Function() notifyParent;
ListVessel({Key key, #required this.notifyParent}) : super(key: key);
#override
_ListVesselState createState() => _ListVesselState();
}
class _ListVesselState extends State<ListVessel> {
#override
Widget build(BuildContext context) {
return ListView.separated(
separatorBuilder: (context, index) => Divider(color: Colors.blueGrey),
itemCount: otherVessels.length,
itemBuilder: (context, index) {
return ListTile(
title: Text("Name: "+otherVessels[index]["shipName"]),
onTap: () {
showDialog (
context: context,
builder: (_){
return otherTap(idx:index);
}
);
}
);
},
);
}
}
}
From above code, each tile (vessel) can be tapped and it calls otherTap() method. otherTap() method displays a simple dialog (popup) that contains the details of the tapped vessel.
Below is the code for otherTap().
class otherTap extends StatefulWidget{
otherTap({Key key, #required this.idx}) : super(key: key);
final int idx;
#override
_otherTapState createState() => new _otherTapState();
}
class _otherTapState extends State<otherTap>{
#override
Widget build(BuildContext context){
_isDialogShowing = true;
return SimpleDialog(
title: Text(otherVessels[widget.idx]["shipName"]),
children: <Widget>[
SimpleDialogOption(
child: Text('MMSI : ' + otherVessels[widget.idx]['MMSI']),
)
],
);
}
}
I have a global boolean variable (_isDialogShowing) to keep tracking if the dialog is showing.
Now i want the showdialog (popup) to dismiss after 5 second.
I use Navigator.pop() to dismiss the dialog in the MyApp function. I put it inside setstate() function.
void main() {
runApp(
MyApp(storage: CounterStorage()),
);
}
class MyApp extends StatefulWidget {
MyApp({Key key, #required this.storage}) : super(key: key);
final CounterStorage storage;
#override
State<StatefulWidget> createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
final appTitle = 'Testing applicatin';
void _update(BuildContext context) async {
await Future.delayed(Duration(milliseconds: 5000));
setState(() {
if(_isDialogShowing){
_isDialogShowing = false;
Navigator.pop(context);
//Navigator.of(context).pop();
}
});
}
#override
Widget build(BuildContext context) {
_update(context);
return new WillPopScope(
onWillPop: null,
child: new MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
home: MyHomePage(title: appTitle),
routes: {
Routes.home: (context) => MyHomePage(),
Routes.settings: (context) => SettingsPage(),
},
),
);
}
}
However the navigator.pop methods above doesn't close the popup.
Can anyone help?
You need to call pop on the context that you receive in builder of showDialog(), only then the dialog will pop that was created by that showDialog().
Replace your showDialog() with following and it will work for you:
showDialog(
context: context,
builder: (BuildContext context) {
Future.delayed(Duration(seconds: 5)).then((_) {
Navigator.pop(context);
});
return otherTap(idx:index);
},
);
I've solved this issue using
Navigator.of(context, rootNavigator: true).pop();

Categories

Resources