web-dev-qa-db-ja.com

OnBackPressed()をフラグメントに実装する方法

Android Activityで実装する方法と同じように、Android FragmentでonBackPressed()を実装できる方法はありますか?

フラグメントのライフサイクルにはonBackPressed()がありません。 Android 3.0のフラグメントでonBackPressed()を上書きするための他の方法はありますか?

私はこのようにして解決し、ActivityのonBackPressedを上書きします。すべてのFragmentTransactionはコミット前はaddToBackStackです。

@Override
public void onBackPressed() {

    int count = getSupportFragmentManager().getBackStackEntryCount();

    if (count == 0) {
        super.onBackPressed();
        //additional code
    } else {
        getSupportFragmentManager().popBackStack();
    }

}
265
Hw.Master

最善の解決策は

Javaソリューション

簡単なインターフェースを作成します。

public interface IOnBackPressed {
    /**
     * If you return true the back press will not be taken into account, otherwise the activity will act naturally
     * @return true if your processing has priority if not false
     */
    boolean onBackPressed();
}

そしてあなたの活動の中で

public class MyActivity extends Activity {
    @Override public void onBackPressed() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
       if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
          super.onBackPressed();
       }
    } ...
}

最後にあなたのフラグメントに:

public class MyFragment extends Fragment implements IOnBackPressed{
   @Override
   public boolean onBackPressed() {
       if (myCondition) {
            //action not popBackStack
            return true; 
        } else {
            return false;
        }
    }
}

コトリンソリューション

1 - インターフェースの作成

interface IOnBackPressed {
    fun onBackPressed(): Boolean
}

2 - あなたの活動を準備する

class MyActivity : AppCompatActivity() {
    override fun onBackPressed() {
        val fragment =
            this.supportFragmentManager.findFragmentById(R.id.main_container)
        (fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let {
            super.onBackPressed()
        }
    }
}

3 - ターゲットフラグメントに実装する

class MyFragment : Fragment(), IOnBackPressed {
    override fun onBackPressed(): Boolean {
        return if (myCondition) {
            //action not popBackStack
            true
        } else {
            false
        }
    }
}
96
Maxime Jallu

@HaMMeRedによると、ここでの答えは疑似コードです。あなたの主なアクティビティはBaseActivityと呼ばれているとしましょう(SlidingMenu libの例のように)。手順は次のとおりです。

まず、汎用的なメソッドを持つために、インターフェイスとそのインターフェイスを実装するクラスを作成する必要があります。

  1. クラスインタフェースOnBackPressedListenerを作成します。

    public interface OnBackPressedListener {
        public void doBack();
    }
    
  2. OnBackPressedListenerのスキルを実装するクラスを作成する

    public class BaseBackPressedListener implements OnBackPressedListener {
        private final FragmentActivity activity;
    
        public BaseBackPressedListener(FragmentActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void doBack() {
            activity.getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
    }
    
  3. これからは、コードBaseActivityとそのフラグメントに取り組みます。

  4. クラスの上にプライベートリスナーを作成しますBaseActivity

    protected OnBackPressedListener onBackPressedListener;
    
  5. BaseActivityにリスナーを設定するメソッドを作成します。

    public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
        this.onBackPressedListener = onBackPressedListener;
    }
    
  6. オーバーライドonBackPressedでは、そのようなものを実装します。

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null)
            onBackPressedListener.doBack();
        else
            super.onBackPressed();
    
  7. onCreateViewのフラグメントにリスナーを追加します

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        activity = getActivity();
    
        ((BaseActivity)activity).setOnBackPressedListener(new BaseBackPressedListener(activity));
    
        View view = ... ;
    //stuff with view
    
        return view;
    }
    

さて、フラグメントをクリックして戻ると、今度はカスタムオンバックメソッドをキャッチする必要があります。

91
deadfish

これは私のために働いた: https://stackoverflow.com/a/27145007/3934111

@Override
public void onResume() {
    super.onResume();

    if(getView() == null){
        return;
    }

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
                // handle back button's click listener
                return true;
            }
            return false;
        }
    });
}
73

そのような機能が必要な場合は、アクティビティでそれをオーバーライドしてから、すべてのフラグメントにYourBackPressedインターフェースを追加する必要があります。これは、戻るボタンが押されたときに必ず関連するフラグメントを呼び出します。

編集:以前の答えを追加したいのですが。

私が今日これをやるとしたら、私は他のパネルがマスター/メインコンテンツパネルと一斉に更新することを期待しているなら、私はブロードキャスト、あるいはおそらく注文されたブロードキャストを使うでしょう。

サポートライブラリの LocalBroadcastManager はこれを手助けすることができます、そしてあなたは単にonBackPressedで放送を送り、あなたが気にかけているあなたのフラグメントで購読するだけです。私は、Messagingはより分離された実装であり、より良い規模になると思うので、今では私の公式な実装推奨となるでしょう。メッセージのフィルタとしてIntentのアクションを使うだけです。あなたの新しく作成したACTION_BACK_PRESSEDを送って、あなたの活動からそれを送って、そして関連する断片の中でそれを聞いてください。

63
HaMMeReD

そのどれも実装が簡単でもなく、最適な方法で機能することもありません。

フラグメントは、仕事をするメソッド呼び出しonDetachを持ちます。

@Override
    public void onDetach() {
        super.onDetach();
        PUT YOUR CODE HERE
    }

これは仕事をします。

43
Sterling Diaz

以下のようにフラグメント間を遷移している間にaddToBackStackを追加するだけです。

fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();

もしあなたがaddToBackStack(null)を書いたなら、それはそれ自身でそれを処理しますが、あなたがタグを与えるなら、あなたはそれを手動で処理するべきです。

22
Rudi

この質問といくつかの答えは5年以上前のものなので、私の解決策を教えてください。これは@oyenigunからの回答へのフォローアップと近代化です

UPDATE: この記事の最後に、Activityをまったく含まない抽象フラグメント拡張を使用した代替の実装を追加しました。これは、入れ子になったフラグメントを含むより複雑なフラグメント階層を持つ人に役立ちます。それは異なるバック動作を必要とします。

私はこれを実装する必要がありました。私が使用するフラグメントの中には、ポップアップ表示される小さい情報ビューなど、戻るボタンで却下したい小さいビューがあるものがあります。フラグメント内の戻るボタン.

まず、インターフェースを定義します

public interface Backable {
    boolean onBackPressed();
}

私はBackable(私は命名規則のためのものです)と呼ぶこのインターフェースは、boolean値を返さなければならない単一のメソッドonBackPressed()を持っています。戻るボタンを押したときに戻るイベントが「吸収」されたかどうかを知る必要があるため、ブール値を適用する必要があります。 trueを返すことはそれが持っていることを意味し、それ以上のアクションは必要ありません、そうでなければ、falseはデフォルトのバックアクションがまだ行われなければならないと言います。このインターフェースはそれ自身のファイルであるべきです(できればinterfacesという別のパッケージに入っているのが望ましいです)。覚えておいて、あなたのクラスをパッケージに分けることは良い習慣です。

次に、一番上のフラグメントを見つけます

バックスタックの最後のFragmentオブジェクトを返すメソッドを作成しました。タグを使用しています…IDを使用している場合は、必要な変更を加えます。私はナビゲーション状態などを扱うユーティリティクラスにこの静的メソッドを持っています...もちろん、それがあなたに最も適した場所に置いてください。啓示のために、私はNavUtilsというクラスに私のものを入れました。

public static Fragment getCurrentFragment(Activity activity) {
    FragmentManager fragmentManager = activity.getFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 0) {
        String lastFragmentName = fragmentManager.getBackStackEntryAt(
                fragmentManager.getBackStackEntryCount() - 1).getName();
        return fragmentManager.findFragmentByTag(lastFragmentName);
    }
    return null;
}

バックスタックカウントが0より大きいことを確認してください。そうしないと、実行時にArrayOutOfBoundsExceptionがスローされる可能性があります。 0より大きくない場合はnullを返します。後でnull値をチェックします...

3番目に、フラグメントで実装する

戻るボタンの動作をオーバーライドする必要がある場所で、Backableインターフェースをいずれかのフラグメントで実装します。実装メソッドを追加してください。

public class SomeFragment extends Fragment implements 
        FragmentManager.OnBackStackChangedListener, Backable {

...

    @Override
    public boolean onBackPressed() {

        // Logic here...
        if (backButtonShouldNotGoBack) {
            whateverMethodYouNeed();
            return true;
        }
        return false;
    }

}

onBackPressed()オーバーライドに、必要なロジックをすべて入れてください。バックボタンを not にしてバックスタックをポップしたい場合(デフォルトの動作)、 true を返して、バックイベントが吸収されたことを確認してください。そうでなければ、falseを返します。

最後に、あなたの活動の中で...

onBackPressed()メソッドをオーバーライドして、このロジックを追加してください。

@Override
public void onBackPressed() {

    // Get the current fragment using the method from the second step above...
    Fragment currentFragment = NavUtils.getCurrentFragment(this);

    // Determine whether or not this fragment implements Backable
    // Do a null check just to be safe
    if (currentFragment != null && currentFragment instanceof Backable) {

        if (((Backable) currentFragment).onBackPressed()) {
            // If the onBackPressed override in your fragment 
            // did absorb the back event (returned true), return
            return;
        } else {
            // Otherwise, call the super method for the default behavior
            super.onBackPressed();
        }
    }

    // Any other logic needed...
    // call super method to be sure the back button does its thing...
    super.onBackPressed();
}

現在のフラグメントをバックスタックで取得し、次にnullチェックを行い、それがBackableインタフェースを実装しているかどうかを判断します。そうであれば、そのイベントが吸収されたかどうかを判別してください。もしそうなら、私たちはonBackPressed()で終わりましたそして戻ることができます。それ以外の場合は、通常のバックプレスとして扱い、スーパーメソッドを呼び出します。

アクティビティを含まない2番目のオプション

時々、あなたはActivityにこれを全く処理させたくない、そしてあなたはフラグメントの中で直接それを処理する必要がある。しかし、誰があなたの言うことを言っています バックプレスのAPIを使ってフラグメントを持つことはできません フラグメントを新しいクラスに拡張するだけです。

Fragmentを拡張してView.OnKeyListnerインターフェースを実装する抽象クラスを作成します。

import Android.app.Fragment;
import Android.os.Bundle;
import Android.view.KeyEvent;
import Android.view.View;

public abstract class BackableFragment extends Fragment implements View.OnKeyListener {

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        view.setOnKeyListener(this);
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_UP) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                onBackButtonPressed();
                return true;
            }
        }

        return false;
    }

    public abstract void onBackButtonPressed();
}

ご覧のとおり、BackableFragmentを拡張するフラグメントは、View.OnKeyListenerインターフェースを使用して自動的にバッククリックをキャプチャします。標準のロジックを使用して、実装されたonBackButtonPressed()メソッド内から抽象onKey()メソッドを呼び出すだけで、戻るボタンを押すのがわかります。戻るボタン以外のキークリックを登録する必要がある場合は、フラグメントのonKey()をオーバーライドするときに必ずsuperメソッドを呼び出すようにしてください。そうしないと、抽象化の動作がoverrideされます。

使い方は簡単で、拡張して実装するだけです。

public class FragmentChannels extends BackableFragment {

    ...

    @Override
    public void onBackButtonPressed() {
        if (doTheThingRequiringBackButtonOverride) {
            // do the thing
        } else {
            getActivity().onBackPressed();
        }
    }

    ...
}

スーパークラスのonBackButtonPressed()メソッドは抽象メソッドであるため、一度拡張したらonBackButtonPressed()を実装する必要があります。フラグメントクラス内でアクションを実行するだけでよく、プレスの吸収をActivityに中継する必要がないため、voidを返します。 確認してください 戻るボタンの操作が不要な場合はActivity onBackPressed()メソッドを呼び出します。それ以外の場合は、戻るボタンが無効になります。

警告 お分かりのように、これはキーリスナーをフラグメントのルートビューに設定します。それに焦点を合わせる必要があります。このクラスを拡張する編集テキスト(または他のフォーカスを盗むビュー)がフラグメントに含まれている場合(または他の内部フラグメントまたは同じビューを持つ場合)、それを個別に処理する必要があります。 EditTextを拡張する についての記事があります。

誰かがこれが役に立つことを願っています。ハッピーコーディング.

19
mwieczorek

解決策は簡単です。

1)すべてのフラグメントが拡張する基本フラグメントクラスがある場合は、このコードをそのクラスに追加します。それ以外の場合は、そのような基本フラグメントクラスを作成します。

 /* 
 * called when on back pressed to the current fragment that is returned
 */
 public void onBackPressed()
 {
    // add code in super class when override
 }

2)Activityクラスで、次のようにonBackPressedをオーバーライドします。

private BaseFragment _currentFragment;

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

3)あなたのフラグメントクラスに、あなたの希望するコードを追加してください:

 @Override
 public void onBackPressed()
 {
    setUpTitle();
 }
13
IdoT

まあ私はこのようにそれをやった、そしてそれは私のために働く

シンプルなインターフェース

FragmentOnBackClickInterface.Java

public interface FragmentOnBackClickInterface {
    void onClick();
}

実装例

MyFragment.Java

public class MyFragment extends Fragment implements FragmentOnBackClickInterface {

// other stuff

public void onClick() {
       // what you want to call onBackPressed?
}

それからアクティビティのonBackPressedをオーバーライドするだけです。

    @Override
public void onBackPressed() {
    int count = getSupportFragmentManager().getBackStackEntryCount();
    List<Fragment> frags = getSupportFragmentManager().getFragments();
    Fragment lastFrag = getLastNotNull(frags);
    //nothing else in back stack || nothing in back stack is instance of our interface
    if (count == 0 || !(lastFrag instanceof FragmentOnBackClickInterface)) {
        super.onBackPressed();
    } else {
        ((FragmentOnBackClickInterface) lastFrag).onClick();
    }
}

private Fragment getLastNotNull(List<Fragment> list){
    for (int i= list.size()-1;i>=0;i--){
        Fragment frag = list.get(i);
        if (frag != null){
            return frag;
        }
    }
    return null;
}
7
Błażej

onBackPressed()はフラグメントをActivityから切り離します。

@Sterling Diazの回答によると、彼は正しいと思います。しかしいくつかの状況は間違っているでしょう。 (例:画面回転)

だから、私たちはisRemoving()が目標を達成するかどうかを検出できると思います。

onDetach()またはonDestroyView()に書くことができます。仕事です。

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

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(isRemoving()){
        // onBackPressed()
    }
}
7
林奕忠

これはちょっとしたコツです。

 getActivity().onBackPressed();

誰かに役立つことを願っています:)

7
Shahid Sarwar

あなたは以下のようにあなたのプロジェクトにインターフェースを追加するべきです。

public interface OnBackPressed {

     void onBackPressed();
}

そして、あなたはあなたのフラグメントにこのインターフェースを実装するべきです。

public class SampleFragment extends Fragment implements OnBackPressed {

    @Override
    public void onBackPressed() {
        //on Back Pressed
    }

}

そして、あなたは以下のようにあなたの活動onBackPressedイベントの下でこのonBackPressedイベントを引き起こすことができます。

public class MainActivity extends AppCompatActivity {
       @Override
        public void onBackPressed() {
                Fragment currentFragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - 1);
                if (currentFragment instanceof OnBackPressed) {  
                    ((OnBackPressed) currentFragment).onBackPressed();
                }
                super.onBackPressed();
        }
}
7
oyenigun

OnDestroyView()はどうですか?

@Override
public void onDestroyView() {
    super.onDestroyView();
}
6

EventBusを使用している場合は、おそらくはるかに単純な解決策です。

あなたのフラグメントでは:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    EventBus.getDefault().register(this);
}

@Override
public void onDetach() {
    super.onDetach();
    EventBus.getDefault().unregister(this);
}


// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
    getSupportFragmentManager().popBackStack();
}

アクティビティクラスでは、次のように定義できます。

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
    super.onBackPressed();
}

@Override
public void onBackPressed() {
    EventBus.getDefault().post(new BackPressedMessage(true));
}

BackPressedMessage.Javaは単なるPOJOオブジェクトです。

これはとてもきれいで、インターフェースや実装の面倒はありません。

6
Akshat

これが私の解決策です:

MyActivity.Java:

public interface OnBackClickListener {
        boolean onBackClick();
    }

    private OnBackClickListener onBackClickListener;

public void setOnBackClickListener(OnBackClickListener onBackClickListener) {
        this.onBackClickListener = onBackClickListener;
    }

@Override
    public void onBackPressed() {
        if (onBackClickListener != null && onBackClickListener.onBackClick()) {
            return;
        }
        super.onBackPressed();
    }

そしてFragment:

((MyActivity) getActivity()).setOnBackClickListener(new MyActivity.OnBackClickListener() {
    @Override
    public boolean onBackClick() {
        if (condition) {
            return false;
        }

        // some codes

        return true;
    }
});
5
@Override
public void onResume() {
    super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
                // handle back button
                replaceFragmentToBackStack(getActivity(), WelcomeFragment.newInstance(bundle), tags);

                return true;
            }

            return false;
        }
    });
}
4

ただ次の手順に従ってください:

フラグメントを追加している間は常に

fragmentTransaction.add(R.id.fragment_container, detail_fragment, "Fragment_tag").addToBackStack(null).commit();

次に、メインアクティビティでonBackPressed()をオーバーライドします

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
    getSupportFragmentManager().popBackStack();
} else {
    finish();
}

アプリの戻るボタンを処理するには、

Fragment f = getActivity().getSupportFragmentManager().findFragmentByTag("Fragment_tag");
if (f instanceof FragmentName) {
    if (f != null) 
        getActivity().getSupportFragmentManager().beginTransaction().remove(f).commit()               
}

それでおしまい!

3
Divya

アクティビティライフサイクルでは、FragmentActivityまたはAppCompatActivityを使用した場合、常にAndroidの戻るボタンがFragmentManagerトランザクションを処理します。

バックスタックを処理するために、バックスタックの数を処理したりタグを付けたりする必要はありませんが、フラグメントを追加または置換する間はフォーカスを維持する必要があります。次のスニペットを見つけて、戻るボタンのケースを処理してください。

    public void replaceFragment(Fragment fragment) {

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (!(fragment instanceof HomeFragment)) {
            transaction.addToBackStack(null);
        }
        transaction.replace(R.id.activity_menu_fragment_container, fragment).commit();
    }

ここでは、ホームフラグメントがアプリケーションのホームページであるため、ホームフラグメントのスタックを追加しません。 HomeToLinkにaddToBackStackを追加すると、アプリはアクティブになっているすべてのフレームを削除するのを待ちますが、画面が空白になるので、次の条件を維持します。

if (!(fragment instanceof HomeFragment)) {
            transaction.addToBackStack(null);
}

これで、以前に追加したアクティビティのフラグメントが表示され、HomeFragmentに到達したときにアプリが終了することがわかります。次のスニペットを見ることもできます。

@Override
public void onBackPressed() {

    if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
        closeDrawer();
    } else {
        super.onBackPressed();
    }
}
3
Deva

非常に短くて甘い答え:

getActivity().onBackPressed();

私の場合のシナリオ全体の説明:

MainActivityにFragmentAがあり、FragmentAからFragmentBを開いています(FragmentBはFragmentAの子フラグメントまたはネストしたフラグメントです)

 Fragment duedateFrag = new FragmentB();
 FragmentTransaction ft  = getFragmentManager().beginTransaction();
 ft.replace(R.id.container_body, duedateFrag);
 ft.addToBackStack(null);
 ft.commit();

さて、あなたがFragmentBからFragmentAに行きたいのであれば、単にgetActivity().onBackPressed();をFragmentBに入れることができます。

3
Parsania Hardik

戻るボタンを押したときにアクティビティが終了するように、ft.addToBackStack()メソッドを実装しないでください。

proAddAccount = new ProfileAddAccount();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, proAddAccount);
//fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
3

AndroidXリリースノート によると、androidx.activity 1.0.0-alpha01がリリースされ、既存のComponentActivityFragmentActivityの新しい基本クラスであるAppCompatActivityが導入されました。そしてこのリリースは私たちに新しい機能をもたらします:

アクティビティのメソッドをオーバーライドする必要なく、OnBackPressedCallbackを介してaddOnBackPressedCallbackを登録してonBackPressed()コールバックを受け取ることができます。

2
TonnyL

最善の解決策

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v7.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {
    @Override
    public void onBackPressed() {

        FragmentManager fm = getSupportFragmentManager();
        for (Fragment frag : fm.getFragments()) {
            if (frag == null) {
                super.onBackPressed();
                finish();
                return;
            }
            if (frag.isVisible()) {
                FragmentManager childFm = frag.getChildFragmentManager();
                if (childFm.getFragments() == null) {
                    super.onBackPressed();
                    finish();
                    return;
                }
                if (childFm.getBackStackEntryCount() > 0) {
                    childFm.popBackStack();
                    return;
                }
                else {

                    fm.popBackStack();
                    if (fm.getFragments().size() <= 1) {
                        finish();
                    }
                    return;
                }

            }
        }
    }
}
2
Shervin Gharib

私はそれが遅すぎることを知っていますが、私は先週同じ問題を抱えていました。答えのどれも私を助けませんでした。それから私はコードで遊んでいました、そして、私はすでに断片を追加したので、これはうまくいきました。

アクティビティで、OnPageChangeListenerViewPagerを設定して、ユーザがいつ2番目のアクティビティにいるかがわかるようにします。彼が2番目のアクティビティにいる場合は、次のようにブールtrueを作成します。

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setCurrentItem(0);
    mViewPager.addOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // TODO Auto-generated method stub
                mSectionsPagerAdapter.instantiateItem(mViewPager, position);
                if(position == 1)
                    inAnalytics = true;
                else if(position == 0)
                    inAnalytics = false;
        }

        @Override
        public void onPageScrolled(int position, float arg1, int arg2) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
            // TODO Auto-generated method stub

        }
    });

戻るボタンが押されたときはいつでもブール値をチェックし、現在の項目をあなたの最初のフラグメントに設定します。

@Override
public void onBackPressed() {
    if(inAnalytics)
        mViewPager.setCurrentItem(0, true);
    else 
        super.onBackPressed();
}
1
zeeshan khan

わかりました私はついに良い解決策を見つけました。

あなたのアクティビティのonCreate()の中であなたのフラグメントは以下のようにバックスタック変更リスナーを追加します:

    fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            List<Fragment> f = fragmentManager.getFragments();
            //List<Fragment> f only returns one value
            Fragment frag = f.get(0);
            currentFragment = frag.getClass().getSimpleName();
        }
    });

(フラグメントを変更するたびに、現在のフラグメントStringが現在のフラグメントの名前になります。その後、アクティビティonBackPressed()では、次のように戻るボタンのアクションを制御できます。

    @Override
    public void onBackPressed() {

    switch (currentFragment) {
        case "FragmentOne":
            // your code here
            return;
        case "FragmentTwo":
            // your code here
            return;
        default:
            fragmentManager.popBackStack();
            // default action for any other fragment (return to previous)
    }

}

この方法がうまくいくことを確認できます。

1
Haider Malik

バックプレスを処理するためにアクティビティにフラグメントを登録できます。

interface BackPressRegistrar {
    fun registerHandler(handler: BackPressHandler)
    fun unregisterHandler(handler: BackPressHandler)
}

interface BackPressHandler {
    fun onBackPressed(): Boolean
}

使用法:

フラグメントで:

private val backPressHandler = object : BackPressHandler {
    override fun onBackPressed(): Boolean {
        showClosingWarning()
        return false
    }
}

override fun onResume() {
    super.onResume()
    (activity as? BackPressRegistrar)?.registerHandler(backPressHandler)
}

override fun onStop() {
    (activity as? BackPressRegistrar)?.unregisterHandler(backPressHandler)
    super.onStop()
}

活動中:

class MainActivity : AppCompatActivity(), BackPressRegistrar {


    private var registeredHandler: BackPressHandler? = null
    override fun registerHandler(handler: BackPressHandler) { registeredHandler = handler }
    override fun unregisterHandler(handler: BackPressHandler) { registeredHandler = null }

    override fun onBackPressed() {
        if (registeredHandler?.onBackPressed() != false) super.onBackPressed()
    }
}
1
Francis

An Activity Aがあり、B、C、Dのように3つのフラグメントを作成する場合は非常に簡単です。フラグメントBまたはCおよびonBackPressedの場合は、毎回フラグメントDに移動する必要があります。onBackPressed()をオーバーライドするだけです。メインアクティビティAのメソッド、そして任意のフラグメントにジャンプするときには、メインアクティビティAでそのフラグメントを認識するための TAGまたは名前 のフラグメントを渡します。

私はあなたがそれを容易に理解することができるそれによってその一つの例を与えています....

if (savedInstanceState == null) {

   getSupportFragmentManager().beginTransaction().add(R.id.container, new C_fragment(),"xyz").commit();

}

または、フラグメントBからフラグメントCに移動している場合は、バックプレスでフラグメントDを表示します。

btn.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {

        getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container, new C_frament(), "xyz").commit();
        ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Fragment C");
    }
});

これで、メインアクティビティでonBackPressed()メソッドをオーバーライドするだけです。

@Override
public void onBackPressed() {
    FragmentManager fragmentManager =getSupportFragmentManager();
    if (((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")) != null && ((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")).isVisible()) {
        Fragment fragment = new D_Fragment();
        fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
        getSupportActionBar().setTitle("D fragment ");
    } else {
        super.onBackPressed();
    }
}

私は次のように別のアプローチを使いました:

  • アクティビティとそのフラグメントの間で通信するための Ottoイベントバス
  • 呼び出し側のフラグメントが定義するRunnableにラップされたcustom back アクションを含むActivity内のStack
  • onBackPressedが制御アクティビティで呼び出されると、最新のカスタム back アクションがポップされ、そのRunnableが実行されます。スタックに何もなければ、デフォルトのsuper.onBackPressed()が呼ばれます。

サンプルコードを使用した完全なアプローチは、 this other SO question に対する回答として here を含みます。

1
aoemerson

パブリッククラスMyActivityがActivityを拡張

protected OnBackPressedListener onBackPressedListener;

public interface OnBackPressedListener {
    void doBack();
}

public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
    this.onBackPressedListener = onBackPressedListener;
}

@Override
public void onBackPressed() {
    if (onBackPressedListener != null)
        onBackPressedListener.doBack();
    else
        super.onBackPressed();
} 

@Override
protected void onDestroy() {
    onBackPressedListener = null;
    super.onDestroy();
}

}

あなたのフラグメントに以下を追加し、mainactivityのインターフェースを実装することを忘れないでください。

public class MyFragment extends Framgent implements MyActivity.OnBackPressedListener {
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
         ((MyActivity) getActivity()).setOnBackPressedListener(this);
    }

@Override
public void doBack() {
    //BackPressed in activity will call this;
}

}
1
joelvarma

mainActivityについて

protected DrawerHomeActivity.OnBackPressedListener onBackPressedListener;

public interface OnBackPressedListener {
    void doBack();
}

public void setOnBackPressedListener(DrawerHomeActivity.OnBackPressedListener onBackPressedListener) {
    this.onBackPressedListener = onBackPressedListener;
}

@Override
public void onBackPressed() {
    if (onBackPressedListener != null) {
        onBackPressedListener.doBack();


    }
    else
        super.onBackPressed();



}

フラグメントの基本アクティビティ/フラグメントを実装

implements DrawerHomeActivity.OnBackPressedListener

DraweHomeActivityは私の基本活動です

((DrawerHomeActivity) getActivity()).setOnBackPressedListener(this);

メソッドdoBackを作成します。

@Override
public void doBack() {
    //call base fragment 
    }
0
Mahesh Pandit

OnBackPressed()をフラグメントリスナーでオーバーライドする必要があります。方法は次のとおりです。

https://stackoverflow.com/a/51228447/7451779

0
Haider Malik

単にonKeyUp()でそれをする:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {

    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // do something
        return true;  // return true if back handled, false otherwise
    }

    return super.onKeyUp(keyCode, event);
}
0
b0b

私は同じ問題を抱えていました、そして私はそれのために新しいリスナーを作成し、私の断片で使用されました。

1 - あなたのアクティビティはリスナーインターフェースとリスナーのリストを持つべきです

2 - リスナーを追加および削除するためのメソッドを実装する必要があります

3 - onBackPressedメソッドをオーバーライドして、リスナーのいずれかがバックプレスを使用するかどうかを確認する必要があります。

public class MainActivity ... {

    /**
     * Back press listener list. Used for notifying fragments when onBackPressed called
     */
    private Stack<BackPressListener> backPressListeners = new Stack<BackPressListener>();


    ...

    /**
     * Adding new listener to back press listener stack
     * @param backPressListener
     */
    public void addBackPressListener(BackPressListener backPressListener) {
        backPressListeners.add(backPressListener);
    }

    /**
     * Removing the listener from back press listener stack
     * @param backPressListener
     */
    public void removeBackPressListener(BackPressListener backPressListener) {
        backPressListeners.remove(backPressListener);
    }


    // Overriding onBackPressed to check that is there any listener using this back press
    @Override
    public void onBackPressed() {

        // checks if is there any back press listeners use this press
        for(BackPressListener backPressListener : backPressListeners) {
            if(backPressListener.onBackPressed()) return;
        }

        // if not returns in the loop, calls super onBackPressed
        super.onBackPressed();
    }

}

4 - あなたのフラグメントはバックプレス用のインターフェースを実装しなければなりません

5 - バックプレスのリスナーとしてフラグメントを追加する必要があります

6 - フラグメントがこのバックプレスを使用している場合は、onBackPressedからtrueを返す必要があります。

7 - 重要 - リストからフラグメントを削除する必要がありますonDestroy

public class MyFragment extends Fragment implements MainActivity.BackPressListener {


    ...

    @Override
    public void onAttach(Activity activity) {
        super.onCreate(savedInstanceState);

        // adding the fragment to listener list
        ((MainActivity) activity).addBackPressListener(this);
    }

    ...

    @Override
    public void onDestroy() {
        super.onDestroy();

        // removing the fragment from the listener list
        ((MainActivity) getActivity()).removeBackPressListener(this);
    }

    ...

    @Override
    public boolean onBackPressed() {

        // you should check that if this fragment is the currently used fragment or not
        // if this fragment is not used at the moment you should return false
        if(!isThisFragmentVisibleAtTheMoment) return false;

        if (isThisFragmentUsingBackPress) {
            // do what you need to do
            return true;
        }
        return false;
    }
}

最新のフラグメントから開始できるようにするために、ArrayListの代わりに使用されるStackがあります。バックスタックにフラグメントを追加している間も問題があるかもしれません。そのため、バックプレスを使用している間、断片が見えるかどうかを確認する必要があります。そうでなければ、フラグメントの1つがイベントを使用し、最新のフラグメントはバックプレスでクローズされません。

私はこれが皆のための問題を解決することを願っています。

0
eluleci

onBackPressed()フラグメントを処理する簡単な方法

ステップ1:アクティビティに静的なブール値を作成します。

public static Fragment_one;

ステップ2: On CreateメソッドのMainActivity(フラグメントを保持するアクティビティ)で、宣言します

Fragment_one=true;

ステップ3: MainActivityでonBackPressed()をオーバーライドする

@Override
public void onBackPressed() {

    if(Fragment_one) {
     //Back key pressed on fragment one

    }else {
      //Back key pressed on fragment two
    }
}

ステップ4: On fragment_oneonCreateViewメソッド宣言

MainActivity.Fragment_one=true;

ステップ5 On fragment_twoonCreateViewメソッド宣言

MainActivity.Fragment_one=false;

注:このメソッドは、2つのフラグメントにのみ適用できます。

0
Elaiya

Fragment: / BaseFragmentがメソッドを配置するようにする:

 public boolean onBackPressed();

活動:

@Override
public void onBackPressed() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            if (!fragment.isVisible()) continue;

            if (fragment instanceof BaseFragment && ((BaseFragment) fragment).onBackPressed()) {
                return;
            }
        }
    }

    super.onBackPressed();
}

あなたのアクティビティはアタッチされたそして目に見えるフラグメントの上に走りそしてそれらのそれぞれで onBackPressed() を呼び出しそしてそれらの一つが 'true'を返すなら中止するでしょう。

0
   @Override
   public boolean onKeyDown(int keyCode, KeyEvent event)
    {
       if ((keyCode == KeyEvent.KEYCODE_BACK))
  {
           finish();
    }
       return super.onKeyDown(keyCode, event);
    }

キーダウン関連のメソッドをコメントアウトするだけで、addToBackStackが機能するようになりました。ありがとう

0
Tasnuva oshin