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();
}
}
最善の解決策は
簡単なインターフェースを作成します。
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;
}
}
}
interface IOnBackPressed {
fun onBackPressed(): Boolean
}
class MyActivity : AppCompatActivity() {
override fun onBackPressed() {
val fragment =
this.supportFragmentManager.findFragmentById(R.id.main_container)
(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let {
super.onBackPressed()
}
}
}
class MyFragment : Fragment(), IOnBackPressed {
override fun onBackPressed(): Boolean {
return if (myCondition) {
//action not popBackStack
true
} else {
false
}
}
}
@HaMMeRedによると、ここでの答えは疑似コードです。あなたの主なアクティビティはBaseActivity
と呼ばれているとしましょう(SlidingMenu libの例のように)。手順は次のとおりです。
まず、汎用的なメソッドを持つために、インターフェイスとそのインターフェイスを実装するクラスを作成する必要があります。
クラスインタフェースOnBackPressedListener
を作成します。
public interface OnBackPressedListener {
public void doBack();
}
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);
}
}
これからは、コードBaseActivity
とそのフラグメントに取り組みます。
クラスの上にプライベートリスナーを作成しますBaseActivity
protected OnBackPressedListener onBackPressedListener;
BaseActivity
にリスナーを設定するメソッドを作成します。
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
オーバーライドonBackPressed
では、そのようなものを実装します。
@Override
public void onBackPressed() {
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
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;
}
さて、フラグメントをクリックして戻ると、今度はカスタムオンバックメソッドをキャッチする必要があります。
これは私のために働いた: 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;
}
});
}
そのような機能が必要な場合は、アクティビティでそれをオーバーライドしてから、すべてのフラグメントにYourBackPressed
インターフェースを追加する必要があります。これは、戻るボタンが押されたときに必ず関連するフラグメントを呼び出します。
編集:以前の答えを追加したいのですが。
私が今日これをやるとしたら、私は他のパネルがマスター/メインコンテンツパネルと一斉に更新することを期待しているなら、私はブロードキャスト、あるいはおそらく注文されたブロードキャストを使うでしょう。
サポートライブラリの LocalBroadcastManager
はこれを手助けすることができます、そしてあなたは単にonBackPressed
で放送を送り、あなたが気にかけているあなたのフラグメントで購読するだけです。私は、Messagingはより分離された実装であり、より良い規模になると思うので、今では私の公式な実装推奨となるでしょう。メッセージのフィルタとしてIntent
のアクションを使うだけです。あなたの新しく作成したACTION_BACK_PRESSED
を送って、あなたの活動からそれを送って、そして関連する断片の中でそれを聞いてください。
そのどれも実装が簡単でもなく、最適な方法で機能することもありません。
フラグメントは、仕事をするメソッド呼び出しonDetachを持ちます。
@Override
public void onDetach() {
super.onDetach();
PUT YOUR CODE HERE
}
これは仕事をします。
以下のようにフラグメント間を遷移している間にaddToBackStack
を追加するだけです。
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();
もしあなたがaddToBackStack(null)
を書いたなら、それはそれ自身でそれを処理しますが、あなたがタグを与えるなら、あなたはそれを手動で処理するべきです。
この質問といくつかの答えは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を拡張する についての記事があります。
誰かがこれが役に立つことを願っています。ハッピーコーディング.
解決策は簡単です。
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();
}
まあ私はこのようにそれをやった、そしてそれは私のために働く
シンプルなインターフェース
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;
}
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()
}
}
これはちょっとしたコツです。
getActivity().onBackPressed();
誰かに役立つことを願っています:)
あなたは以下のようにあなたのプロジェクトにインターフェースを追加するべきです。
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();
}
}
OnDestroyView()はどうですか?
@Override
public void onDestroyView() {
super.onDestroyView();
}
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オブジェクトです。
これはとてもきれいで、インターフェースや実装の面倒はありません。
これが私の解決策です:
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;
}
});
@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;
}
});
}
ただ次の手順に従ってください:
フラグメントを追加している間は常に
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()
}
それでおしまい!
アクティビティライフサイクルでは、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();
}
}
非常に短くて甘い答え:
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に入れることができます。
戻るボタンを押したときにアクティビティが終了するように、ft.addToBackStack()メソッドを実装しないでください。
proAddAccount = new ProfileAddAccount();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, proAddAccount);
//fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
AndroidXリリースノート によると、androidx.activity 1.0.0-alpha01
がリリースされ、既存のComponentActivity
とFragmentActivity
の新しい基本クラスであるAppCompatActivity
が導入されました。そしてこのリリースは私たちに新しい機能をもたらします:
アクティビティのメソッドをオーバーライドする必要なく、OnBackPressedCallback
を介してaddOnBackPressedCallback
を登録してonBackPressed()
コールバックを受け取ることができます。
最善の解決策
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;
}
}
}
}
}
私はそれが遅すぎることを知っていますが、私は先週同じ問題を抱えていました。答えのどれも私を助けませんでした。それから私はコードで遊んでいました、そして、私はすでに断片を追加したので、これはうまくいきました。
アクティビティで、OnPageChangeListener
にViewPager
を設定して、ユーザがいつ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();
}
わかりました私はついに良い解決策を見つけました。
あなたのアクティビティの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)
}
}
この方法がうまくいくことを確認できます。
バックプレスを処理するためにアクティビティにフラグメントを登録できます。
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()
}
}
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();
}
}
私は次のように別のアプローチを使いました:
Runnable
にラップされたcustom back アクションを含むActivity内のStackonBackPressed
が制御アクティビティで呼び出されると、最新のカスタム back アクションがポップされ、そのRunnable
が実行されます。スタックに何もなければ、デフォルトのsuper.onBackPressed()
が呼ばれます。サンプルコードを使用した完全なアプローチは、 this other SO question に対する回答として here を含みます。
パブリッククラス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;
}
}
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
}
OnBackPressed()をフラグメントリスナーでオーバーライドする必要があります。方法は次のとおりです。
単に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);
}
私は同じ問題を抱えていました、そして私はそれのために新しいリスナーを作成し、私の断片で使用されました。
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つがイベントを使用し、最新のフラグメントはバックプレスでクローズされません。
私はこれが皆のための問題を解決することを願っています。
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つのフラグメントにのみ適用できます。
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'を返すなら中止するでしょう。
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}
キーダウン関連のメソッドをコメントアウトするだけで、addToBackStackが機能するようになりました。ありがとう