Я создал приложение для чата, но у меня возникают проблемы с его экраном чата, потому что я использую пакет emoji_picker_flutte для отображения доски смайлов, и я реализовал его так, что всякий раз, когда доска смайлов была на логической переменной, это было true, и наоборот, и если пользователь сначала использует жест обратной навигации, доска смайлов исчезнет, а затем, если пользователь снова использует жест обратной навигации, страница всплывет.
При использовании WillPopScope проблем не было, но в последнее время с PopScope их нет. Я попытался поместить весь код в onPopInvoked, как было сказано при миграции, с canPop, установленным на false, но это не работает.
Я также попытался использовать весь код в отдельной функции с типом возвращаемого значения как bool и использовать эту функцию на canPop, но это не удалось, потому что canPop работает все время, пока эта страница включена, при использовании таким образом доска смайлов даже не появляется и потому что при нажатии кнопки эмодзи и повороте переменной true она сразу становится false, при этом все работает нормально.
bool _willpop() {
if (_showEmoji) {
setState(() => _showEmoji = !_showEmoji);
return false;
} else {
return true;
}
}
PopScope (
canPop = _willpop();
child:...
)
Другой путь
_willpop(bool p) {
if (p) return;
if (_showEmoji) {
change();
return false;
} else {
return true;
}
}
PopScope (
canPop: false,
onPopInvoked: (didpop) => _willpop(didpop),
child:...
)
оба способа не работают, может кто-нибудь предложить лучший способ для этого





Во втором случае, если p истинно, ничего не возвращайте. Просто удалите эту строку.
if (p) return;
Теперь, если _showEmoji имеет значение true, просто измените его значение и вызовите setState, но если оно ложно, используйте Navigator.pop(context) для всплывающего окна.
_willpop(bool p) {
if (_showEmoji) {
change();
} else {
Navigator.pop(context);
}
}
Причина, по которой ваш первый метод не работает, может заключаться в том, что когда вы установили _showEmoji=true, вы не вызвали setState(), поэтому новый виджет PopScope не был создан с canPop как false, но все равно как true, что позволяет пользователю вернуться назад.
Но я советую не использовать первый метод, потому что этот метод вызывается при сборке виджета, и вы вызываете setState() при сборке виджета, который снова перестраивает виджет, если условие соответствует. Если условия не обрабатываются должным образом, виджет будет перестраиваться снова и снова.
Вот почему используйте второй метод, который вызывается только тогда, когда пользователь действительно пытается вернуться, а не при сборке виджета.
Вы можете использовать второй метод с установленным состоянием. В своем ответе я сказал не использовать его для первого метода. Когда вы вызываете setState внутри fn, который передается canPop и выполняется каждый раз при построении виджета. Но onPopInvoked — это обратный вызов fn, на который не влияет сборка виджета, он похож на кнопку. Вот почему сказано использовать второй метод. И хорошо, что вы нашли решение.
Я нашел решение, вот решение, и оно работает так, как я хотел
bool _showEmoji = false;
void change() => setState(() => _showEmoji = !_showEmoji);
_willpop() {
if (_showEmoji) change();
}
PopScope(
canPop: !_showEmoji,
onPopInvoked: (_) => _willpop(),
child:...,
),
onPopInvoked запросил void fn. Так что ничего возвращать не нужно было. _willpop() должен быть пустым fn.
Благодарим вас за вклад в сообщество Stack Overflow. Возможно, это правильный ответ, но было бы очень полезно предоставить дополнительные пояснения к вашему коду, чтобы разработчики могли понять ваши рассуждения. Это особенно полезно для новых разработчиков, которые не так хорошо знакомы с синтаксисом или пытаются понять концепции. Не могли бы вы отредактировать свой ответ, включив в него дополнительную информацию на благо сообщества?
да, я обновил его сейчас, прежде чем использовать тот же код, что и в Willpopscope.
Итак, мне следует использовать второй метод без setState onPopInvoked? bool _willpop() { if (_showEmoji) { _showEmoji = !_showEmoji; вернуть ложь; } Еще {вернуть истину; } }