185 votes

Comment puis-je revenir correctement à une activité parentale ?

J'ai 2 activités (A et B) dans mon application Android et j'utilise une intention pour aller de l'activité A à l'activité B. L'utilisation de parent_activity est activée :

 <activity
        android:name=".B"
        android:label="B" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
  </activity>

J'utilise également un thème qui prévoit un bouton UP.

Ainsi, après avoir appelé l'activité B, je peux utiliser le bouton UP pour revenir à l'activité A. Le problème est que l'application semble appeler la fonction onCreate() -fonction de l'activité A à nouveau et ce n'est pas le comportement dont j'ai besoin. J'ai besoin que l'activité A ressemble à ce qu'elle était avant que j'appelle l'activité B.

Existe-t-il un moyen d'y parvenir ?

EDIT

Je n'ai pas écrit de code pour lancer l'activité B à partir de l'activité A. Je pense qu'il est généré automatiquement par Eclipse.

La classe B ressemble :

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}

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

0 votes

Affichez votre code, pour démarrer l'activité A à partir de B..

0 votes

Si je comprends bien, vous pouvez utiliser startActivityForResult() et renvoyer un resultCode ou autre.

0 votes

Veuillez mettre à jour votre réponse correcte étiquetée ! La CORRECTE réponse vient de LorenzCK - pas de l'utilisateur...... ! Le fait de marquer cette réponse comme correcte est trompeur et fait en sorte qu'encore plus de programmeurs comprennent mal la navigation vers le haut par opposition à la navigation vers le bas !

346voto

LorenzCK Points 2819

Vous avez déclaré l'activité A avec la norme launchMode dans le manifeste Android. Selon la documentation cela signifie ce qui suit :

Le système crée toujours une nouvelle instance de l'activité dans la tâche cible et y achemine l'intention.

Par conséquent, le système est contraint de recréer l'activité A (c'est-à-dire d'appeler onCreate ) même si la pile de tâches est gérée correctement.

Pour résoudre ce problème, vous devez modifier le manifeste en ajoutant l'attribut suivant à la déclaration de l'activité A :

android:launchMode="singleTop"

Nota: en appelant finish() (comme suggéré comme solution auparavant) fonctionne uniquement quand vous êtes complètement sûr que l'instance de l'activité B à laquelle vous mettez fin se trouve au-dessus d'une instance de l'activité A. Dans les flux de travail plus complexes (par exemple, le lancement de l'activité B à partir d'une notification), cela peut ne pas être le cas et vous devez lancer correctement l'activité A à partir de B.

11 votes

Voici l'explication tirée de la documentation Android, Les modes "standard" et "singleTop" diffèrent l'un de l'autre sur un seul point : Chaque fois qu'il y a une nouvelle intention pour une activité "standard", une nouvelle instance de la classe est créée pour répondre à cette intention. Chaque instance gère une seule intention. De même, une nouvelle instance d'une activité "singleTop" peut également être créée pour gérer une nouvelle intention. Toutefois, si la tâche cible possède déjà une instance existante de l'activité au sommet de sa pile, cette instance recevra la nouvelle intention (dans un appel onNewIntent()) ; une nouvelle instance n'est pas créée.

0 votes

Notez que selon la documentation navigateUpFromSameTask(...) devrait ajouter FLAG_ACTIVITY_CLEAR_TOP a upIntent (via navigateUpTo(...) ce qui devrait donner lieu au même comportement (selon ce guide ), mais le drapeau n'est jamais activé - et donc cette réponse a un sens

83voto

user370305 Points 46287

Réponse actualisée : Up Navigation Design

Vous devez déclarer quelle activité est le parent approprié pour chaque activité. Cela permet au système de faciliter les modèles de navigation tels que Up, car le système peut déterminer l'activité mère logique à partir du fichier manifeste.

Pour cela, vous devez déclarer votre activité parente dans le tag Activity avec l'attribut

android:parentActivityName

Comme,

<!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.app_name.A" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name=".B"
        android:label="B"
        android:parentActivityName="com.example.app_name.A" >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
    </activity>

Avec l'activité parentale déclarée de cette façon, vous pouvez naviguer vers le parent approprié comme ci-dessous,

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Donc quand vous appelez NavUtils.navigateUpFromSameTask(this); cette méthode, elle termine l'activité en cours et démarre (ou reprend) l'activité parente appropriée. Si l'activité parente cible se trouve dans la pile arrière de la tâche, elle est avancée comme défini par la méthode FLAG_ACTIVITY_CLEAR_TOP .

Et pour afficher le bouton Up, vous devez déclarer setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

Ancienne réponse : (Sans navigation vers le haut, navigation vers le bas par défaut)

Cela ne se produit que si vous recommencez l'activité A à partir de l'activité B.

Utilisation de startActivity() .

Au lieu de cela, à partir de l'activité A, commencez l'activité B en utilisant les éléments suivants startActivityForResult() et de passer outre onActivtyResult() dans l'activité A.

Maintenant, dans l'activité B, il suffit d'appeler finish() sur le bouton Up. Donc maintenant vous avez dirigé vers l'activité A onActivityResult() sans créer de nouveau l'activité A..

0 votes

Je ne sais pas où est appelé startActivity() dans l'activité B. J'ai posté le code source de l'activité B...

18 votes

Au lieu de la ligne de code NavUtils.navigateUpFromSameTask(this); écrire finish() .

4 votes

On peut se demander comment il se fait que Google ne mentionne rien sur finish() o startActivityForResult() dans leur documentation sur la navigation ( developer.Android.com/design/patterns/navigation.html ) ?

23voto

androidnewbie Points 129

J'ai eu à peu près la même configuration qui a conduit au même comportement indésirable. Pour moi, cela a fonctionné : j'ai ajouté l'attribut suivant à une activité A dans la section Manifest.xml de mon application :

android:launchMode="singleTask"

Voir cet article pour plus d'explications.

1 votes

De mon point de vue, la solution correcte au problème. Cela se comportera comme si vous appeliez finish() si l'activité existe dans la pile des tâches. Si ce n'est pas le cas, elle sera créée et démarrée.

5 votes

Ce n'est pas la bonne façon de procéder car cela créera une nouvelle tâche inutilement à chaque fois, vous devriez plutôt utiliser le launchMode="singleTop".

7voto

donald Points 170

Une meilleure façon d'y parvenir est d'utiliser deux choses : l'appel :

NavUtils.navigateUpFromSameTask(this);

Maintenant, pour que cela fonctionne, il faut que votre fichier manifeste indique que l'activité A a une activité parente B. L'activité parente n'a besoin de rien. Dans les versions 4 et supérieures, vous obtiendrez une belle flèche arrière sans effort supplémentaire (cela peut être fait sur les versions inférieures également avec un peu de code, je le mettrai ci-dessous). Vous pouvez définir ces données dans l'onglet manifeste->application de l'interface graphique (faites défiler vers le bas jusqu'au nom de l'activité parente, et mettez-le à la main).

Nœud de soutien :

si vous souhaitez prendre en charge une version inférieure à la version 4, vous devez également inclure les métadonnées. Cliquez avec le bouton droit de la souris sur l'activité, ajoutez->métadonnées, nom =Android.support.PARENT_ACTIVITY et valeur = votre.activité.complète.nom

pour obtenir la belle flèche dans les versions inférieures également :

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

veuillez noter que vous aurez besoin de la version 7 de la bibliothèque de support pour que tout cela fonctionne, mais cela en vaut la peine !

1voto

Luis Valadez Points 19

Essayez ceci :

Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
    intent = getIntent();   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}  

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X