使用导航时防止Flutter应用程序转到上一个主状态或上一个主屏幕

svmlkihl  于 2023-03-24  发布在  Flutter
关注(0)|答案(3)|浏览(117)

我正在构建一个flutter应用程序,并使用导航将数据从addTaskScreen传递到homeScreen。但是当我从homeScreen按下后退按钮时,应用程序将进入以前的状态并显示以前未更新的数据。如何防止它。
下面是我的两个屏幕的代码,
主屏幕:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:todo/database/database.dart';
import 'package:todo/hidden_screen.dart';
import 'package:todo/models/task_model.dart';
// import 'package:sqflite/sqflite.dart';

import 'add_todo_screen.dart';

// ignore: use_key_in_widget_constructors
class HomeScreen extends StatefulWidget {
// const HomeScreen({super.key});

@override
State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
late Future<List<Task>> _taskList;

final DateFormat _dateFormatter = DateFormat('MMM dd, yyyy');

// ignore: unused_field
final DatabaseHelper _databaseHelper = DatabaseHelper.instance;

@override
void initState() {
  super.initState();
 _updateTaskList();
}

_updateTaskList() {
_taskList = DatabaseHelper.instance.getTaskList();
}

Widget _buildTask(Task task) {
 return Column(
  children: [
    ListTile(
      title: Text(
        task.title!,
        style: TextStyle(
          fontFamily: 'Mordred',
          color: task.status == 0 ? Colors.black87 : Colors.black12,
          decoration: task.status == 0
              ? TextDecoration.none
              : TextDecoration.lineThrough,
        ),
      ),
      subtitle: Text(
        '${_dateFormatter.format(task.date!)} - ${task.priority}',
        style: TextStyle(
          fontFamily: 'Mordred',
          color: task.status == 0 ? Colors.black87 : Colors.black12,
          decoration: task.status == 0
              ? TextDecoration.none
              : TextDecoration.lineThrough,
        ),
      ),
      trailing: Checkbox(
        checkColor: Colors.black,
        tristate: false,
        onChanged: (value) {
          // print(value);
          task.status = value! ? 1 : 0;
          DatabaseHelper.instance.updateTask(task);
          _updateTaskList();
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (_) => HomeScreen(),
            ),
          );
        },
        activeColor: Theme.of(context).primaryColor,
        value: task.status == 1 ? true : false,
      ),
      onTap: () => Navigator.push(
        context,
        CupertinoPageRoute(
          builder: (_) => AddToDoScreen(
            updateTaskList: _updateTaskList(),
            task: task,
          ),
        ),
      ),
    ),
    const Divider(
      height: 20,
      thickness: 20,
    )
  ],
);
}
@override
Widget build(BuildContext context) {
 return Scaffold(
  backgroundColor: Colors.lime[100],
  appBar: AppBar(
    leading: GestureDetector(
      onLongPress: () {
        Navigator.push(
          context,
          CupertinoPageRoute(
            builder: (_) => const HiddenScreen(),
          ),
        );
      },
      child: const Padding(
        padding: EdgeInsets.fromLTRB(10, 10, 0, 5),
        // child: Icon(
        //   Icons.tornado_rounded,
        //   color: Colors.lime[100],
        //   size: 30,
        // ),
        // child: Image.asset(
        //   'assets/images/box.gif',
        //   fit: BoxFit.cover,
        // ),
        child: CircleAvatar(
          backgroundImage: AssetImage(
            'assets/images/box.gif',
          ),
        ),
      ),
    ),
    title: const Text(
      'Things To Do',
      style: TextStyle(fontFamily: 'Binary X CHR', fontSize: 36),
    ),
    elevation: 60,
  ),
  floatingActionButton: FloatingActionButton(
    backgroundColor: Theme.of(context).primaryColor,
    onPressed: () {
      Navigator.push(
        context,
        CupertinoPageRoute(
          builder: (_) => AddToDoScreen(
            updateTaskList: _updateTaskList,
          ),
        ),
      );
    },
    child: const Icon(Icons.ac_unit_rounded),
  ),
  body: FutureBuilder(
    future: _taskList,
    builder: (context, AsyncSnapshot snapshot) {
      if (!snapshot.hasData) {
        return const Center(
          child: CircularProgressIndicator(),
        );
      }

      final int completedTaskCount = snapshot.data!
          .where((Task task) => task.status == 1)
          .toList()
          .length;

      return ListView.builder(
        padding: const EdgeInsets.symmetric(vertical: 20.0),
        itemCount: int.parse(snapshot.data!.length.toString()) + 1,
        itemBuilder: (BuildContext conntext, int index) {
          if (index == 0) {
            return Padding(
              padding: const EdgeInsets.symmetric(
                horizontal: 40,
                vertical: 30,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  const Text(
                    'MY TASK',
                    style: TextStyle(
                      color: Colors.black38,
                      fontFamily: 'Binary X CHR',
                      fontSize: 40,
                      // fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  Text(
                    '$completedTaskCount out of ${snapshot.data.length} Completed',
                    style: const TextStyle(
                      color: Colors.black38,
                      fontFamily: 'Binary X CHR',
                      fontSize: 20,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ],
              ),
            );
          }
          return _buildTask(snapshot.data![index - 1]);
        },
      );
     },
    ),
   );
  }
}

添加任务屏幕:

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:todo/database/database.dart';
import 'package:todo/home_screen.dart';

import 'models/task_model.dart';

class AddToDoScreen extends StatefulWidget {
// const AddToDoScreen({super.key});
final Task? task;
final Function? updateTaskList;

const AddToDoScreen({super.key, this.task, this.updateTaskList});

@override
State<AddToDoScreen> createState() => _AddToDoScreenState(); 
}

class _AddToDoScreenState extends State<AddToDoScreen> {
final _formKey = GlobalKey<FormState>();

String _title = '';
String _priority = 'Low';

DateTime _date = DateTime.now();

String btnText = "Add Task";
String titleText = "Add Title";

final TextEditingController _dateController = TextEditingController();

final DateFormat _dateFormatter = DateFormat('MMM dd, yyyy');
final List<String> _priorities = ['Low', 'Medium', 'High'];

@override
void initState() {
  super.initState();

if (widget.task != null) {
  _title = widget.task!.title!;
  _date = widget.task!.date!;
  _priority = widget.task!.priority!;

  setState(() {
    btnText = "Update Task";
    titleText = "Update Task";
  });
} else {
  setState(() {
    btnText = "Add Task";
    titleText = "Add Task";
  });
}
_dateController.text = _dateFormatter.format(_date);
}

@override
void dispose() {
_dateController.dispose();
super.dispose();
}

_handleDatePicker() async {
final DateTime? date = await showDatePicker(
  context: context,
  initialDate: _date,
  firstDate: DateTime(1900),
  lastDate: DateTime(2100),
);
if (date != null && date != _date) {
  setState(() {
    _date = date;
  });
  _dateController.text = _dateFormatter.format(date);
 }
}

_delete() {
 DatabaseHelper.instance.deleteTask(widget.task!.id!);
Navigator.pushReplacement(
  context,
  MaterialPageRoute(
    builder: (_) => HomeScreen(),
  ),
);
widget.updateTaskList!();
}

_submit() {
if (_formKey.currentState!.validate()) {
  _formKey.currentState!.save();

  // print to check if the data is saving to database or not
  // print('$_title, $_date, $_priority');

  Task task = Task(title: _title, date: _date, priority: _priority);

  if (widget.task == null) {
    task.status = 0;
    DatabaseHelper.instance.insertTask(task);

    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (_) => HomeScreen(),
      ),
    );
  } else {
    task.id = widget.task!.id;
    task.status = widget.task!.status;
    DatabaseHelper.instance.updateTask(task);

    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (_) => HomeScreen(),
      ),
    );
    Navigator.pop(
      context,
      MaterialPageRoute(
        builder: (_) => HomeScreen(),
      ),
    );
  }
   widget.updateTaskList!();
 }
}

@override
Widget build(BuildContext context) {
return Scaffold(
  backgroundColor: Colors.lime[100],
  body: GestureDetector(
    onTap: () => FocusScope.of(context).unfocus(),
    child: SingleChildScrollView(
      child: Container(
        padding:
            const EdgeInsets.symmetric(horizontal: 30.0, vertical: 50.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            GestureDetector(
              onTap: () => Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (_) => HomeScreen(),
                ),
              ),
              child: Icon(
                Icons.arrow_back_ios_new_rounded,
                size: 30.0,
                color: Theme.of(context).primaryColor,
              ),
            ),
            const SizedBox(
              height: 20.0,
            ),
            Text(
              titleText,
              style: const TextStyle(
                fontSize: 40,
                fontFamily: 'Mordred',
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(
              height: 10,
            ),
            Form(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.symmetric(
                      vertical: 20.0,
                    ),
                    child: TextFormField(
                      style: const TextStyle(
                        fontSize: 18.0,
                        fontFamily: 'Mordred',
                      ),
                      decoration: InputDecoration(
                        labelText: 'Title',
                        labelStyle: const TextStyle(
                          // color: Colors.black,
                          fontSize: 18,
                          fontFamily: 'Mordred',
                        ),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                      ),
                      validator: (input) => input!.trim().isEmpty
                          ? 'Please enter a task title'
                          : null,
                      onSaved: (input) => _title = input!,
                      initialValue: _title,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(
                      vertical: 20.0,
                    ),
                    child: TextFormField(
                      readOnly: true,
                      controller: _dateController,
                      onTap: _handleDatePicker,
                      style: const TextStyle(
                        fontSize: 18.0,
                        fontFamily: 'Mordred',
                      ),
                      decoration: InputDecoration(
                        labelText: 'Date',
                        labelStyle: const TextStyle(
                          fontSize: 18,
                          fontFamily: 'Mordred',
                        ),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(vertical: 20),
                    child: DropdownButtonFormField(
                      isDense: true,
                      icon: const Icon(Icons.double_arrow_rounded),
                      iconSize: 20,
                      iconEnabledColor: Theme.of(context).primaryColor,
                      iconDisabledColor: Colors.black54,
                      items: _priorities.map((String priority) {
                        return DropdownMenuItem(
                          value: priority,
                          child: Text(
                            priority,
                            style: const TextStyle(
                                color: Colors.black54,
                                fontSize: 18,
                                fontFamily: 'Mordred'),
                          ),
                        );
                      }).toList(),
                      style: const TextStyle(fontSize: 18),
                      decoration: InputDecoration(
                        labelText: 'Priority',
                        labelStyle: const TextStyle(
                          fontSize: 18,
                          fontFamily: 'Mordred',
                        ),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                        ),
                      ),
                      value: _priority,
                      // ignore: unnecessary_null_comparison
                      validator: (input) => _priority == null
                          ? 'Please select a priority level'
                          : null,
                      onChanged: (value) {
                        setState(
                          () {
                            _priority = value.toString();
                          },
                        );
                      },
                    ),
                  ),
                  Container(
                    margin: const EdgeInsets.fromLTRB(0, 10, 0, 10),
                    height: 60.0,
                    width: double.infinity,
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(30),
                    ),
                    child: ElevatedButton(
                      style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all(Colors.lime),
                      ),
                      onPressed: _submit,
                      child: Text(
                        btnText,
                        style: TextStyle(
                          color: Colors.lime[100],
                          fontSize: 20,
                          fontFamily: 'Mordred',
                        ),
                      ),
                    ),
                  ),
                  widget.task != null
                      ? Container(
                          margin: const EdgeInsets.fromLTRB(0, 20, 0, 0),
                          height: 60.0,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(30),
                          ),
                          child: ElevatedButton(
                            style: ButtonStyle(
                              backgroundColor:
                                  MaterialStateProperty.all(Colors.lime),
                            ),
                            onPressed: _delete,
                            child: Text(
                              'Delete Task',
                              style: TextStyle(
                                color: Colors.lime[100],
                                fontSize: 20,
                                fontFamily: 'Mordred',
                              ),
                            ),
                          ),
                        )
                      : const SizedBox.shrink(),
                ],
              ),
            ),
          ],
        ),
      ),
    ),
   ),
  );
 }
}
vlju58qv

vlju58qv1#

您的代码中有以下部分:

Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (_) => HomeScreen(),
      ),
    );
    Navigator.pop(
      context,
      MaterialPageRoute(
        builder: (_) => HomeScreen(),
      ),
    );

这可能会使它进入主屏幕,然后再次弹出到以前的状态?
或许把爆米花拿出来。
如果你仍然在为数据不更新而挣扎,你可能只需要在你的更新调用周围添加一个setState(() {})

7jmck4yq

7jmck4yq2#

不要使用pop,你应该把用户推到页面。就像洋葱一样,应用程序有(以前加载的)层。在AppBar中尝试以下操作:

leading: IconButton(
 icon:Icons(Icons.arrow_back),
 onTap() {
  Navigator.pushAndRemoveUntil(context,
   MaterialPageRoute(
    builder: (BuildContext context) {
     return const Inicio();
    }), (r) {
     return false;
    });}//Maybe you should use a different one if you still want to keep the arrows or something related
),
wgx48brx

wgx48brx3#

谢谢大家的回答。我已经找到了解决方案,它帮助我解决了这个问题。我刚刚使用了pushAndRemoveUntil而不是pushReplacement。
下面是我的代码与问题部分:

// onTap: () => Navigator.pushReplacement(
              //   context,
              //   MaterialPageRoute(
              //     builder: (_) => HomeScreen(),
              //   ),
              // ),

这就是解决办法:

onTap: () => Navigator.of(context).pushAndRemoveUntil(
                MaterialPageRoute(
                  builder: (context) => HomeScreen(),
                ),
                (Route<dynamic> route) => false,
              ),

相关问题