Android - Como substituir o botão "Voltar" para que não termine () minha atividade?


199

Atualmente, tenho uma Atividade que, quando exibida, uma Notificação também será exibida na barra de Notificações.

Isso ocorre para que, quando o Usuário pressionar a tecla Início e a Atividade for empurrada para segundo plano, eles possam voltar à Atividade por meio da Notificação.

O problema surge quando um usuário pressiona o botão Voltar, minha Atividade é destruída, mas a Notificação permanece como eu quero que o usuário possa retornar, mas ainda pode acessar a Atividade por meio da Notificação. Mas quando um USUÁRIO tenta isso, recebo Null Pointers como uma tentativa de iniciar uma nova atividade em vez de trazer de volta a antiga.

Então, basicamente, quero que o botão Voltar atue exatamente da mesma forma que o botão Início e aqui está como tentei até agora:


        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event)  {
            if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5
                    && keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) {
                Log.d("CDA", "onKeyDown Called");
                onBackPressed();
            }

            return super.onKeyDown(keyCode, event);
        }

        public void onBackPressed() {
            Log.d("CDA", "onBackPressed Called");
            Intent setIntent = new Intent(Intent.ACTION_MAIN);
            setIntent.addCategory(Intent.CATEGORY_HOME);
            setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(setIntent); 

            return;
        }   

No entanto, o código acima ainda parece permitir que minha Atividade seja destruída. Como posso impedir que minha Atividade seja destruída quando o botão Voltar é pressionado?


Existe uma pergunta semelhante: stackoverflow.com/questions/2459848/… #
aleung


Também acho que você precisa alterar seu código para `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <` deve se tornar um >.
SudoPlz

1
Mesmo se você resolver isso, você ainda deve lidar com a possibilidade do sistema matar o seu aplicativo, certo? Quero dizer, o caso nulo ainda é possível? Ou se o sistema matar seu aplicativo por qualquer motivo, isso também removerá sua notificação? Acho que isso deve ser um problema, pois o objetivo de uma notificação é existir mesmo que o aplicativo não exista.
Página Inicial>

Veja aqui o exemplo do código do aplicativo freakyjolly.com/how-to-add-back-arrow-in-android-activity
Code Spy

Respostas:


276

Remova seu ouvinte de chaves ou retorne truequando tiver KEY_BACK.

Você só precisa do seguinte para pegar a chave de volta (Certifique-se para não chamar super- em onBackPressed()).

Além disso, se você planeja executar um serviço em segundo plano, verifique startForeground()e tenha uma notificação em andamento, caso contrário o Android matará seu serviço se precisar liberar memória.

@Override
public void onBackPressed() {
   Log.d("CDA", "onBackPressed Called");
   Intent setIntent = new Intent(Intent.ACTION_MAIN);
   setIntent.addCategory(Intent.CATEGORY_HOME);
   setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(setIntent);
}

70

Foi mais fácil implementá-lo apenas com uma linha de código:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}

Essa deve ser a resposta aceita. Isso faz exatamente o que a pergunta está fazendo e está usando a funcionalidade integrada limpa.
Shadoninja

Obrigado :) você pode elaborar o conceito por trás disso?
Farrukh Faizy

1
Você simplesmente substitui o evento onBackPressed (), fazendo com que ele mova a atividade para trás.
Squirrelkiller

1
Esta solução não trará a atividade de volta quando você reiniciar o aplicativo na tela inicial (se houver outra atividade na pilha de tarefas).
IgorGanapolsky

12

Acho que o que você deseja é não substituir o botão voltar (isso não parece uma boa idéia - o sistema operacional Android define esse comportamento, por que alterá-lo?), Mas usar o Ciclo de Vida da Atividade e manter suas configurações / dados no evento onSaveInstanceState (Bundle) .

@Override
onSaveInstanceState(Bundle frozenState) {
    frozenState.putSerializable("object_key",
        someSerializableClassYouWantToPersist);
    // etc. until you have everything important stored in the bundle
}

Em seguida, você usa onCreate (Bundle) para obter tudo desse pacote persistente e recriar seu estado.

@Override
onCreate(Bundle savedInstanceState) {
    if(savedInstanceState!=null){ //It could be null if starting the app.
        mCustomObject = savedInstanceState.getSerializable("object_key");
    }
    // etc. until you have reloaded everything you stored
}

Considere o código psuedo acima para apontar na direção certa. A leitura do Ciclo de Vida da Atividade deve ajudá-lo a determinar a melhor maneira de realizar o que você está procurando.


Oi Kiswa, isso é verdade, não quero alterar o comportamento padrão. Tentei usar o onSavedInstanceState e ele não estava funcionando, mas acredito que percebi meu erro agora. Graças
Donal Rafferty

5
Eu me deparei com pelo menos algumas situações em que queria simular o comportamento padrão da pilha de atividades sem realmente iniciar novas atividades. Nesses casos, acho que é apropriado substituir o comportamento padrão onBackPressed (). Em geral, porém, eu concordo: evite substituir.
Matt Briançon

4
Eu concordo com @Matt. Atualmente, estou trabalhando em um jogo de plataforma cruzada que usa o NDK. Como tal, é mais fácil se tudo for uma única atividade. Por esse motivo, o comportamento padrão do botão Voltar é escapar do aplicativo, que não é o que a maioria dos usuários espera. Então, eu tive que sobrescrever o comportamento padrão para fazer com que a atividade se comportasse de maneira diferente, como se o usuário tivesse realmente participado de uma atividade diferente, e sair do aplicativo apenas em determinadas circunstâncias.
Leif Andersen

1
O onSaveInstanceState não está salvando os dados uma pergunta completamente diferente?
Ted

@ Ted -se você está dizendo que, além do onSaveInstanceState, também é necessário haver um código que persista nos dados de aplicativos que não são da interface do usuário, então eu concordo. Assim que você abandonar o primeiro plano, seu aplicativo poderá ser desativado sem aviso adicional. Sempre deve salvar tudo o que importa. Por outro lado, acho que os métodos do ciclo de vida do aplicativo serão chamados independentemente da técnica usada para ocultar o aplicativo, mas mantê-lo por perto, portanto, não será necessário adicionar lógica de salvamento apenas para este caso. Seu aplicativo precisa desse código nos lugares certos, independentemente.
Home

11

simplesmente faça isso ..

@Override
public void onBackPressed() {
    //super.onBackPressed();
}

comentando o //super.onBackPressed (); fará o truque


1
Uma observação útil, mas isso não fará com que o botão voltar não faça nada, como se estivesse quebrado? Isso não é uma coisa boa a se fazer - confusa e irritante para os usuários. O IMHO deve adicionar lógica a partir de outra resposta, para atuar como o botão Início, conforme solicitado em questão. A resposta aceita menciona que eles não estavam deliberadamente chamando super método.
Página

Sim você está absolutamente certo. Ele simplesmente substituirá o botão Voltar e não fará nada até você colocar alguma lógica lá. Pode ser uma condição para pressionar duas vezes o botão para fechar o aplicativo ou você apenas deseja desativar uma operação em andamento (caixa de diálogo de progresso) etc.
androCoder-BD / 02/16 /

5

Tente o seguinte:

@Override
public void onBackPressed() {
    finish();
}

3

Caso você queira lidar com o comportamento do botão voltar (na parte inferior do telefone) e do botão home (o da esquerda da barra de ação), essa atividade personalizada que estou usando no meu projeto pode ajudá-lo .

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

/**
 * Activity where the home action bar button behaves like back by default
 */
public class BackActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupHomeButton();
    }

    private void setupHomeButton() {
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onMenuHomePressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    protected void onMenuHomePressed() {
        onBackPressed();
    }
}

Exemplo de uso em sua atividade:

public class SomeActivity extends BackActivity {

    // ....

    @Override
    public void onBackPressed()
    {
        // Example of logic
        if ( yourConditionToOverride ) {
            // ... do your logic ...
        } else {
            super.onBackPressed();
        }
    }    
}

1
@Override
public void onBackPressed() {
// Put your code here.
}

//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() {
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);
}
Just write this above or below the onCreate Method(within the class)

0

Em Kotlin:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    // Handle the back button event
}

Para mais informações, você pode verificar isso .

Há também uma pergunta específica sobre como substituir o botão Voltar no Kotlin.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.