親アクティビティに正しく戻るにはどうすればよいですか?


179

私のAndroidアプリケーションには2つのアクティビティ(AおよびB)があり、インテントを使用してアクティビティAからアクティビティBに移動します。parent_activityの使用が有効になっています。

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

また、UPボタンを提供するテーマも使用しています。

したがって、アクティビティを呼び出した後、BIはUPボタンを使用してアクティビティAに戻ることができます。問題は、アプリケーションがアクティビティAのonCreate()関数を再度呼び出しているようで、これが必要な動作ではないことです。アクティビティBを呼び出す前と同じように見えるアクティビティAが必要です。

これを達成する方法はありますか?

前もって感謝します

編集:

アクティビティAからアクティビティBを開始するコードは記述していません。Eclipseによって自動生成されると思います。

クラスBは次のようになります。

    @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);
}

BからAの活動を開始するための郵便あなたは、コード..
user370305

私が正しく理解していれば、startActivityForResult()を使用して、resultCodeなどを返すことができます。
Law Gimenez 2012

タグ付きの正解を更新してください!正しい答えはLorenzCKからのものです-ユーザーからではありません......!これに正しいタグを付けると誤解を招きやすくなり、バックナビゲーションではなくナビゲーションを誤解するプログラマーがさらに増えます。
Zordid 2014年

ジー、ここで間違った答えがたくさんあるので、これを片付ける手助けをしてくれませんか...?
Zordid 2014年

@ashiaka-コードデザインごとの正解が更新されました。
user370305 2014年

回答:


334

launchModeAndroidマニフェストの標準でアクティビティAを宣言しました。ドキュメントによると、それは以下を意味します:

システムは常に、ターゲットタスクにアクティビティの新しいインスタンスを作成し、インテントをそのインスタンスにルーティングします。

したがって、システムはアクティビティA(つまり、 onCreateタスクスタックが正しく処理)をます。

この問題を修正するには、マニフェストを変更して、Aアクティビティ宣言に次の属性を追加する必要があります。

android:launchMode="singleTop"

注:呼び出しfinish()(以前の解決策として推奨)は、終了するアクティビティBのインスタンスがアクティビティAのインスタンスの上にあることを完全に確信している場合にのみ機能します。より複雑なワークフロー(たとえば、通知からのアクティビティBの起動)これは当てはまらない場合があり、アクティビティAをBから正しく起動する必要があります。


11
これは、Androidドキュメントの説明です。「標準」モードと「singleTop」モードは、1つの点で互いに異なります。「標準」アクティビティの新しいインテントがあるたびに、クラスの新しいインスタンスが作成され、それに応答しますその意図。各インスタンスは単一のインテントを処理します。同様に、「singleTop」アクティビティの新しいインスタンスを作成して、新しいインテントを処理することもできます。ただし、ターゲットタスクのスタックの最上位にアクティビティの既存のインスタンスが既にある場合、そのインスタンスは新しいインテントを(onNewIntent()呼び出しで)受け取ります。新しいインスタンスは作成されません。
kpsfoo 2013年

ドキュメントに よるnavigateUpFromSameTask(...)と追加FLAG_ACTIVITY_CLEAR_TOPする必要があることに注意してくださいupIntent(介してnavigateUpTo(...)同じ動作をもたらすはずである(によると、このガイド)が、フラグが設定されることはない-従って、この答えは理にかなって
Anigif

82

更新された回答:アップナビゲーションデザイン

各アクティビティに適切な親であるアクティビティを宣言する必要があります。これにより、システムはマニフェストファイルから論理的な親アクティビティを判別できるため、システムはUpなどのナビゲーションパターンを促進できます。

そのため、属性を持つタグアクティビティで親アクティビティを宣言する必要があります

android:parentActivityName

お気に入り、

<!-- 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>

このように宣言された親アクティビティを使用して、以下のようにUpを適切な親に移動できます。

@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);
}

したがってNavUtils.navigateUpFromSameTask(this);、このメソッドを呼び出すと、現在のアクティビティが終了し、適切な親アクティビティが開始(または再開)されます。ターゲットの親アクティビティがタスクのバックスタックにある場合、によって定義されてFLAG_ACTIVITY_CLEAR_TOPいるように、それが繰り上げられます。

そして上ボタンを表示するには、宣言する必要があります setDisplayHomeAsUpEnabled():

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

以前の回答:(アップナビゲーションなし、デフォルトのバックナビゲーション)

アクティビティBからアクティビティAを再開する場合にのみ発生します。

を使用しstartActivity()ます。

これの代わりに、アクティビティAを使用startActivityForResult()してオーバーライドしonActivtyResult()、アクティビティAでオーバーライドします。

今度はアクティビティB finish()でボタンUpを呼び出します。さて、あなたはアクティビティAのonActivityResult()、アクティビティAを再度作成することなく、アクティビティAに移動しました。


アクティビティBのstartActivity()が呼び出される場所がわかりません。アクティビティBのソースコードを投稿しました...
ashiaka

18
コード行の代わりに NavUtils.navigateUpFromSameTask(this); 書きfinish()ます。
user370305

4
それは疑問を抱きます、なぜなぜGoogleはナビゲーションについての彼らのドキュメントfinish()または何も言及していないのですかstartActivityForResult()developer.android.com/design/patterns/navigation.html)?
wired00

これは面倒な回避策のように聞こえます。@LorenzCKの回答ははるかに良いようです。
carmen_munich

NavUtils.navigateUpFromSameTask(this)をご利用いただきありがとうございます。大きなプラス!私は、状況によっては親アクティビティに戻らないfinish()を置き換えるこのようなメソッドを探していました。finish()は基本的に、必ずしも親アクティビティであるとは限らない前のアクティビティに戻ります。
香港

22

私はほぼ同じ設定で同じ不要な動作を引き起こしていました。私にとってこれはうまくManifest.xmlいきました:アプリののアクティビティAに次の属性を追加します:

android:launchMode="singleTask"

詳細については、この記事を参照してください。


1
私の見解では、問題に対する正しい解決策です。これは、アクティビティがタスクスタックに存在する場合に、finish()を呼び出した場合と同じように動作します。そうでない場合は、作成および開始されます。
Johan

5
毎回不必要に新しいタスクを作成するため、これは正しい方法ではありません。代わりに、launchMode = "singleTop"を使用する必要があります。
kpsfoo 2013年

19

古い質問ですが、ウィジェットからアクティビティBディープリンクしたため、以前のすべての回答が機能しなかったため、別の(最もクリーンで最良の)解決策があります。

public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
    Log.v(logTag, "Recreate back stack");
        TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
  } else {
    NavUtils.navigateUpTo(this, upIntent);
  }
}

[ https://stackoverflow.com/a/31350642/570168 ]

しかしまた見なさいhttps : //speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android


7

これを実現するより良い方法は、次の2つを使用することです。

NavUtils.navigateUpFromSameTask(this);

これが機能するには、アクティビティAに親アクティビティBがあることをマニフェストファイルの状態にする必要があります。親アクティビティには何も必要ありません。バージョン4以降では、追加の手間をかけずに素敵な戻る矢印が表示されます(これは、下位バージョンでも小さなコードで実行できます。以下で説明します)このデータは、マニフェスト->アプリケーションタブで設定できます。 GUIで(親アクティビティ名までスクロールし、手動で配置します)

サポートノード:

バージョン4より前のバージョンをサポートする場合は、メタデータも含める必要があります。アクティビティを右クリックし、add-> meta data、name = android.support.PARENT_ACTIVITY、value = your.full.activity.name

下位バージョンでも素敵な矢印を取得するには:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

これをすべて機能させるには、サポートライブラリバージョン7が必要ですが、それだけの価値があります。


5

私のために働いたことは追加していました:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

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

TheRelevantActivity.java予想通り、今それが働いています

追加することを忘れないでください:

getSupportActionbar.setDisplayHomeAsUpEnabled(true);onCreate()方法


4

試しましたがandroid:launchMode="singleTask"、役に立ちませんでした。私のために働いたandroid:launchMode="singleInstance"


アンドロイドの追加:親アクティビティにlaunchMode =「singleInstanceは、」私のために問題を解決した
エミール

4

@LorenCKの答えに加えて、変更

NavUtils.navigateUpFromSameTask(this);

アクティビティを別のアクティビティから開始でき、これが他のアプリによって開始されたタスクの一部になる可能性がある場合は、以下のコードに

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(upIntent)
            .startActivities();
} else {
    NavUtils.navigateUpTo(this, upIntent);
}

これにより、新しいタスクが開始され、アクティビティの親アクティビティが開始されます。これは、Min SDKバージョン<= 15の以下のように、マニフェストで定義できます。

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

またはparentActivityName> 15の場合に使用


注:parentActivityNameSDK> 15を宣言しないと、ランダムクラッシュが発生します
Sourabh

3

親アクティビティ名が不正なAndroid 5.0を使用して同様の問題が発生しました

<activity
        android:name=".DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName=".MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>

親アクティビティ名からcom.example.myfirstappを削除しましたが、正しく動作しました


2

アクティビティマニフェスト情報に属性を追加します

android:launchMode="singleTask"

私にとってはうまくいきます


1
完全なフローは、@ Override public boolean onOptionsItemSelected(MenuItem item){switch(item.getItemId()){case android.R.id.home:NavUtils.navigateUpFromSameTask(this);のようなものです。trueを返します。} return super.onOptionsItemSelected(item); }
Pravesh Kumar 14年

マニフェストに追加<activity android:name = "。MainActivity" android:label = "@ string / title_activity_main"> </ activity> <activity android:name = "。CreateEventActivity" android:label = "@ string / title_activity_create_event" android :launchMode = "singleTask" android:parentActivityName = "。MainActivity"> <meta-data android:name = "android.support.PARENT_ACTIVITY" android:value = "。MainActivity" /> </ activity>
Pravesh Kumar

2

Javaクラス:-

    toolbar = (Toolbar) findViewById(R.id.apptool_bar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setTitle("Snapdeal");

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

マニフェストで:-

<activity
            android:name=".SubActivity"
            android:label="@string/title_activity_sub"
            android:theme="@style/AppTheme" >
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
    </activity>

それはあなたを助けます


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

バックプレスのように


1

これを試して:

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);
}

0

私のマニフェストにandroid:launchMode="singleTop"行って、アクティビティに追加することは、私にとってはトリックでした。

AndroidでUpツールバーのボタンを押した後、前のアクティビティの新しいインスタンスを作成したくなかったため、これにより特に問題が解決しました。代わりに、ナビゲーション階層を上に移動するときに、前のアクティビティの既存のインスタンスを使用しました。

リファレンス:android:launchMode


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.