Existe uma maneira de implementarmos onBackPressed()
no Android Fragment semelhante à maneira como implementamos na Atividade Android?
Como o ciclo de vida do fragmento não possui onBackPressed()
. Existe algum outro método alternativo para substituir os onBackPressed()
fragmentos do Android 3.0?
android
android-fragments
onbackpressed
Android_programmer_camera
fonte
fonte
Respostas:
Eu resolvi dessa maneira substituir
onBackPressed
na Atividade. Todos osFragmentTransaction
sãoaddToBackStack
antes de confirmar:fonte
Na minha opinião, a melhor solução é:
SOLUÇÃO JAVA
Crie uma interface simples:
E na sua atividade
Finalmente em seu fragmento:
SOLUÇÃO KOTLIN
1 - Criar interface
2 - Prepare sua atividade
3 - Implemente no seu fragmento alvo
fonte
R.id.main_container
? Esse é o ID do FragmentPager?.?
) e aplicar não nulos (!!
) pode levar a NPEs - o elenco nem sempre é seguro. Prefiro escreverif ((fragment as? IOnBackPressed)?.onBackPressed()?.not() == true) { ... }
ou mais kotliney(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let { ... }
.onBackPressed()?.takeIf { !it }?.let{...}
?.not()
apenas retorna o inverso.val fragment = this.supportFragmentManager.findFragmentById(R.id.flContainer) as? NavHostFragment val currentFragment = fragment?.childFragmentManager?.fragments?.get(0) as? IOnBackPressed currentFragment?.onBackPressed()?.takeIf { !it }?.let{ super.onBackPressed() }
Isto é para pessoas que usam Kotlin e NavigationControllerDe acordo com a resposta @HaMMeRed, aqui está o pseudocódigo como deve funcionar. Digamos que sua atividade principal seja chamada
BaseActivity
com fragmentos filhos (como no exemplo da SlidingMenu lib). Aqui estão os passos:Primeiro precisamos criar interface e classe que implementa sua interface para ter um método genérico
Criar interface de classe
OnBackPressedListener
Crie uma classe que implemente habilidades de
OnBackPressedListener
Desde agora, trabalharemos em nosso código
BaseActivity
e seus fragmentosCrie um ouvinte privado no topo da sua turma
BaseActivity
criar método para definir o ouvinte
BaseActivity
em substituir
onBackPressed
implementar algo parecidono seu fragmento
onCreateView
você deve adicionar o nosso ouvinteAgora, quando você clica novamente em fragmento, deve capturar seu método personalizado de volta.
fonte
onBackPressed()
qual fragmento estava sendo exibido quando o botão Voltar foi pressionado?((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){ public void doBack() { //...your stuff here }});
Isso funcionou para mim: https://stackoverflow.com/a/27145007/3934111
fonte
Se você quisesse esse tipo de funcionalidade, seria necessário substituí-lo em sua atividade e, em seguida, adicione uma
YourBackPressed
interface a todos os seus fragmentos, que você chama no fragmento relevante sempre que o botão Voltar é pressionado.Editar: gostaria de anexar minha resposta anterior.
Se eu fizesse isso hoje, usaria uma transmissão, ou possivelmente uma transmissão ordenada, se esperasse que outros painéis fossem atualizados em uníssono para o painel de conteúdo principal / principal.
LocalBroadcastManager
na Biblioteca de suporte pode ajudar com isso, e você apenas envia a transmissãoonBackPressed
e assina seus fragmentos que se importam. Penso que o Messaging é uma implementação mais dissociada e seria melhor dimensionada, por isso seria minha recomendação oficial de implementação agora. Basta usar aIntent
ação do como um filtro para sua mensagem. envie o seu recém-criadoACTION_BACK_PRESSED
, envie-o da sua atividade e ouça nos fragmentos relevantes.fonte
LocalBroadcastManager
não pode fazer transmissões encomendadosNada disso é fácil de implementar, nem funcionará da maneira ideal.
Os fragmentos têm uma chamada de método onDetach que fará o trabalho.
ISSO FAZ O TRABALHO.
fonte
isRemoving()
como descrito em stackoverflow.com/a/27103891/2914140 .Se você estiver usando
androidx.appcompat:appcompat:1.1.0
ou acima, poderá adicionar umOnBackPressedCallback
ao seu fragmento da seguinte maneiraConsulte https://developer.android.com/guide/navigation/navigation-custom-back
fonte
androidx-core-ktx
, você pode usarrequireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* code to be executed when back is pressed */ }
LifecycleOwner
parâmetro deve ser adicionado como neste exemplo. Sem ele, qualquer fragmento iniciado depois será chamadohandleBackPressed()
se o botão Voltar for pressionado.Basta adicionar
addToBackStack
enquanto você está fazendo a transição entre seus fragmentos, como abaixo:se você escrever
addToBackStack(null)
, ele cuidará sozinho, mas se você der uma tag, deverá manipulá-la manualmente.fonte
Como esta pergunta e algumas das respostas têm mais de cinco anos, deixe-me compartilhar minha solução. Este é um acompanhamento e modernização da resposta de @oyenigun
ATUALIZAÇÃO: No final deste artigo, adicionei uma implementação alternativa usando uma extensão abstrata de fragmento que não envolverá a atividade, o que seria útil para qualquer pessoa com uma hierarquia de fragmentos mais complexa que envolva fragmentos aninhados que exigem comportamento reverso diferente.
Eu precisava implementar isso porque alguns dos fragmentos que utilizo têm visões menores que eu gostaria de descartar com o botão voltar, como pequenas visões de informações que aparecem, etc., mas isso é bom para quem precisa substituir o comportamento de o botão voltar dentro dos fragmentos.
Primeiro, defina uma interface
Essa interface, que eu chamo
Backable
(sou defensora das convenções de nomenclatura), tem um método únicoonBackPressed()
que deve retornar umboolean
valor. Precisamos impor um valor booleano, pois precisamos saber se o pressionamento do botão voltar "absorveu" o evento back. Retornartrue
significa que sim, e nenhuma ação adicional é necessária; caso contrário,false
diz que a ação de retorno padrão ainda deve ocorrer. Essa interface deve ser seu próprio arquivo (de preferência em um pacote separado chamadointerfaces
). Lembre-se, separar suas classes em pacotes é uma boa prática.Segundo, encontre o fragmento superior
Eu criei um método que retorna o último
Fragment
objeto na pilha de volta. Eu uso tags ... se você usa IDs, faça as alterações necessárias. Eu tenho esse método estático em uma classe de utilitário que lida com estados de navegação, etc ... mas é claro, coloque-o onde melhor lhe convier. Para edificação, coloquei o meu em uma classe chamadaNavUtils
.Verifique se a contagem da pilha traseira é maior que 0, caso contrário,
ArrayOutOfBoundsException
poderá ser lançada em tempo de execução. Se não for maior que 0, retorne nulo. Mais tarde, verificaremos um valor nulo ...Terceiro, implemente em um fragmento
Implemente a
Backable
interface em qualquer fragmento em que você precise substituir o comportamento do botão Voltar. Adicione o método de implementação.Na
onBackPressed()
substituição, coloque qualquer lógica que você precisar. Se você deseja que o botão voltar não apareça a pilha de retorno (o comportamento padrão), retorne verdadeiro , pois seu evento de retorno foi absorvido. Caso contrário, retorne false.Por fim, em sua atividade ...
Substitua o
onBackPressed()
método e adicione esta lógica a ele:Colocamos o fragmento atual na pilha de trás, fazemos uma verificação nula e determinamos se ele implementa nossa
Backable
interface. Se isso acontecer, determine se o evento foi absorvido. Nesse caso, terminamosonBackPressed()
e podemos retornar. Caso contrário, trate-o como uma pressão normal de retorno e chame o super método.Segunda opção para não envolver a atividade
Às vezes, você não quer que a Atividade lide com isso e precisa lidar diretamente com ela dentro do fragmento. Mas quem disse que você não pode ter fragmentos com uma API de contrapressão? Apenas estenda seu fragmento para uma nova classe.
Crie uma classe abstrata que estenda o fragmento e implemente a
View.OnKeyListner
interface ...Como você pode ver, qualquer fragmento que se estenda
BackableFragment
captura automaticamente os cliques anteriores usando aView.OnKeyListener
interface. Basta chamar oonBackButtonPressed()
método abstrato de dentro doonKey()
método implementado usando a lógica padrão para discernir um pressionamento do botão Voltar. Se você precisar registrar cliques de teclas que não sejam o botão Voltar, chame osuper
método ao substituironKey()
seu fragmento, caso contrário, você substituirá o comportamento na abstração.Simples de usar, basta estender e implementar:
Como o
onBackButtonPressed()
método na superclasse é abstrato, depois de estendido, você deve implementaronBackButtonPressed()
. Ele retornavoid
porque só precisa executar uma ação dentro da classe de fragmento e não precisa retransmitir a absorção da impressora de volta para a Atividade. Certifique-se de chamar oonBackPressed()
método Activity se o que você estiver fazendo com o botão voltar não exigir manipulação, caso contrário, o botão voltar será desativado ... e você não quer isso!Advertências Como você pode ver, isso define o ouvinte principal para a visualização raiz do fragmento, e precisaremos focalizá-lo. Se houver textos de edição envolvidos (ou qualquer outra exibição de roubo de foco) em seu fragmento que estenda essa classe (ou outros fragmentos ou exibições internas que tenham a mesma), será necessário lidar com isso separadamente. Há um bom artigo sobre a extensão de um EditText para perder o foco em uma contrapressão.
Espero que alguém ache isso útil. Feliz codificação.
fonte
super.onBackPressed();
duas vezes?currentFragment
. Se o fragmento não for nulo e o fragmento implementar aBackable
interface, nenhuma ação será tomada. Se o fragmento não é nulo e NÃO é implementadoBackable
, chamamos o super método. Se o fragmento for nulo, ele pulará para a última super chamada.currentFragment
não é nulo, é uma instância de Backable e é desanexada (pressionamos oback
botão e fechamos o fragmento), a primeira ocorrência desuper.onBackPressed();
é chamada, depois a segunda.A solução é simples:
1) Se você tem uma classe de fragmento base que todos os fragmentos estendem, adicione esse código à sua classe, caso contrário, crie uma classe de fragmento base
2) Na sua classe Activity, substitua onBackPressed da seguinte maneira:
3) Na sua classe Fragment, adicione o código desejado:
fonte
onBackPressed()
faça com que o fragmento seja desconectado da atividade.De acordo com a resposta de @Sterling Diaz, acho que ele está certo. MAS alguma situação estará errada. (por exemplo, Rodar ecrã)
Então, acho que poderíamos detectar se devemos
isRemoving()
alcançar objetivos.Você pode escrever em
onDetach()
ouonDestroyView()
. É trabalho.fonte
Bem, eu fiz assim, e funcionou para mim
Interface simples
FragmentOnBackClickInterface.java
Implementação de exemplo
MyFragment.java
substitua onBackPressed na atividade
fonte
Você deve adicionar interface ao seu projeto como abaixo;
E então, você deve implementar essa interface no seu fragmento;
E você pode acionar esse evento onBackPressed em suas atividades, como abaixo;
fonte
getActivity().onBackPressed();
, pois invocará a exceção: "java.lang.StackOverflowError: tamanho da pilha 8 MB".Este é apenas um pequeno código que fará o truque:
Espero que ajude alguém :)
fonte
Se você usa o EventBus, provavelmente é uma solução muito mais simples:
e na sua classe Activity você pode definir:
BackPressedMessage.java é apenas um objeto POJO
Isso é super limpo e não há problemas de interface / implementação.
fonte
esta é a minha solução:
fonte
Usando o componente Navigation, você pode fazer o seguinte :
fonte
Que tal usar onDestroyView ()?
fonte
i = i
ouif (1 < 0) {}
.fonte
no seu fragmento adicione o seguinte, não esqueça de implementar a interface da atividade principal.
fonte
Na minha solução (Kotlin);
Estou usando a função onBackAlternative como um parâmetro em BaseActivity .
BaseActivity
Eu tenho uma função para definir onBackPressAlternative em BaseFragment .
BaseFragment
Então meu onBackPressAlternative está pronto para uso em fragmentos.
Fragmentos secundários
fonte
Não implemente o método ft.addToBackStack () para que, ao pressionar o botão Voltar, sua atividade seja concluída.
fonte
Basta seguir estes passos:
Sempre ao adicionar um fragmento,
Em seguida, na atividade principal, substitua
onBackPressed()
Para manipular o botão Voltar no seu aplicativo,
É isso aí!
fonte
No ciclo de vida da atividade, sempre o botão voltar do Android lida com transações do FragmentManager quando usamos FragmentActivity ou AppCompatActivity.
Para lidar com o backstack, não precisamos manipular sua contagem de backstack ou marcar nada, mas devemos manter o foco ao adicionar ou substituir um fragmento. Encontre os seguintes snippets para lidar com as caixas dos botões voltar,
Aqui, não adicionarei pilha traseira ao meu fragmento de página inicial porque é a página inicial do meu aplicativo. Se adicionar addToBackStack ao HomeFragment, o aplicativo aguardará a remoção de todo o problema de atividade, e a tela ficará em branco, mantendo a seguinte condição,
Agora, você pode ver o fragmento adicionado anteriormente na acitvity e o aplicativo será fechado ao acessar o HomeFragment. você também pode procurar nos seguintes trechos.
fonte
Fragmento: Faça um BaseFragment colocando um método:
Atividade:
Sua atividade será executada nos fragmentos anexados e visíveis e chamará BackBackPressed () em cada um deles e abortará se um deles retornar 'verdadeiro' (o que significa que foi tratado, portanto, não há mais ações).
fonte
De acordo com as notas de versão do AndroidX ,
androidx.activity 1.0.0-alpha01
é lançado e apresentaComponentActivity
uma nova classe base dos arquivos existentesFragmentActivity
eAppCompatActivity
. E esta versão nos traz um novo recurso:Agora você pode registrar uma
OnBackPressedCallback
viaaddOnBackPressedCallback
para receberonBackPressed()
retornos de chamada sem precisar substituir o método em sua atividade.fonte
Você pode registrar um fragmento em atividade para lidar com a contrapressão:
uso:
No fragmento:
Em Atividade:
fonte
Fornecer navegação de retorno personalizada manipulando onBackPressed agora é mais fácil com retornos de chamada dentro do fragmento.
Se você deseja a ação de retorno padrão com base em alguma condição, pode usar:
fonte
Dentro do método onCreate do fragmento, adicione o seguinte:
fonte
Melhor solução,
fonte