片段按下后退按钮

问题描述 投票:0回答:18

我现在有一个包含碎片的活动

[1] , [2] , [3] , [4]

如果按下按钮 [3] ,它可以重定向到 [4]

我想实现后退按钮,如下所示..

在 [4] 按回时,返回 [3]

在 [3] 按回时,返回 [2]

在 [1] 处按回车时,活动结束();

说到现在的实现,是完成activity,而不是弹出fragment。你能告诉我我应该做什么或记住什么吗?

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

    if( keyCode==KeyEvent.KEYCODE_BACK) 
    {   

        finish();
    }       

        return super.onKeyDown(keyCode, event); 

}   
android android-fragments back
18个回答
92
投票

这对我有用。

-从活动中调用新片段时添加 .addToBackStack(null)。

    FragmentTransaction mFragmentTransaction = getFragmentManager()
                .beginTransaction();
    ....
    mFragmentTransaction.addToBackStack(null);

-将 onBackPressed() 添加到您的活动中

    @Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        this.finish();
    } else {
        getFragmentManager().popBackStack();
    }
}

62
投票

有史以来最简单的方法:

onResume():

@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's click listener
                Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                return true;
            }
            return false;
        }
    });

}

编辑 1:如果片段有

EditText
.

private EditText editText;

onCreateView():

editText = (EditText) rootView.findViewById(R.id.editText);

onResume():

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

    editText.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                editText.clearFocus();
            }
            return false;
        }
    });

    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
                Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                return true;
            }
            return false;
        }
    });

}

注意: 如果片段中有 EditText,它将起作用。

完成


9
投票

这对我来说是一个可行的解决方案:

dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
                    @Override
                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                        if (keyCode == KeyEvent.KEYCODE_BACK) {
                            // DO WHAT YOU WANT ON BACK PRESSED
                            return true;
                        }
                        return false;
                    }
                });

编辑:您可以用

getView()
替换对话片段。


9
投票

试试这个简单的解决方案:

在你的活动中实现 onBackPressed

 @Override
    public void onBackPressed() {
       if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
            getSupportFragmentManager().popBackStack();
        } else {
            finish();
        }
    }

如果你想在每次向后按时弹出顶部片段,这将起作用。 注意:- 在将片段添加到活动时,始终将事务添加到后台堆栈以使其工作


5
投票

在包含片段的活动中的 onCreate() 中添加一个后台更改侦听器,如下所示:

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

(注:我的 fragmentManager 被声明为全局的) 现在每次更改片段时,currentFragment 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)
    }

}

我可以确认这个方法对我有用。

更新:Kotlin

override fun onBackPressed() {

    when(supportFragmentManager.fragments[0].javaClass.simpleName){
        "FragmentOne" -> doActionOne()
        "FragmentTwo" -> doActionTwo()
        else -> supportFragmentManager.popBackStack()
    }
}

5
投票

Fragment 中按下或处理后退按钮的解决方案

我解决问题的方式我相信它也会帮助你:

1.如果您的片段中没有任何编辑文本框,您可以使用以下代码

这里 MainHomeFragment 是主要片段(当我从第二个片段按下后退按钮时,它也会带我去 MainHomeFragment)

    @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){

                MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =
                        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                fragmentTransaction.commit();

                return true;    
            }    
            return false;
        }
    }); }

2.如果你有另一个名为 Somefragment 的片段,并且它有编辑文本框,那么你可以通过这种方式来完成。

private EditText editText;

然后在,

onCreateView():    
editText = (EditText) view.findViewById(R.id.editText);

然后覆盖 OnResume,

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

    editText.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                editTextOFS.clearFocus();
                getView().requestFocus();
            }
            return false;
        }
    });

    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){

                MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =
                        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                fragmentTransaction.commit();

                return true;

            }

            return false;
        }
    });

}

这就是所有人 (amitamie.com) :-) ;-)


4
投票

更好的解决方案可能是遵循一种设计模式,使后退按钮按下事件从活动片段向下传播到宿主活动。所以,这就像..如果一个活动片段消耗了后压,活动就不会对其采取行动,反之亦然。

一种方法是让所有片段扩展一个基本片段,该片段具有抽象的“boolean onBackPressed()”方法。

@Override
public boolean onBackPressed() {
   if(some_condition)
      // Do something
      return true; //Back press consumed.
   } else {
      // Back-press not consumed. Let Activity handle it
      return false;
   }
}

跟踪 Activity 中的活动片段以及在它的 onBackPressed 回调中写这样的东西

@Override
public void onBackPressed() {
   if(!activeFragment.onBackPressed())
      super.onBackPressed();
   }
}

这篇文章详细描述了这种模式


4
投票

我在这种情况下所做的是从 Activity 中实现 onBackPressed() 函数:

@Override
public void onBackPressed() {
   super.onBackPressed();
   FragmentManager fm = getSupportFragmentManager();
   MyFragment myFragment = (MyFragment) fm.findFragmentById(R.id.my_fragment);

   if((myFragmen.isVisible()){
      //Do what you want to do
   }
}

这对你也有用。


4
投票

如果你在片段中使用 webview 而不是在你的 onCreateView 方法中使用它

webView.setOnKeyListener(new View.OnKeyListener(){

        @Override
        public boolean onKey(View view, int i, KeyEvent keyEvent) {
            if((i==KeyEvent.KEYCODE_BACK)&& webView.canGoBack()){
                webView.goBack();
                return true;
            }
            return false;
        }
    });

并导入这个类

import android.view.KeyEvent;

3
投票

您可以在基本

getFragmentManager().popBackStack()
中使用
Fragment
返回。


2
投票

您还需要检查 Action_Down 或 Action_UP 事件。如果您不检查,那么 onKey() 方法将调用 2 次。

getView().setFocusableInTouchMode(true);
getView().requestFocus();

getView().setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show();
                    return true;
                    }
                }
                return false;
            }
        });

对我来说工作得很好。


2
投票

你可以在onCreateView中使用这个,你可以使用事务或替换

 OnBackPressedCallback callback = new OnBackPressedCallback(true) {
                @Override
                public void handleOnBackPressed() {
                    //what you want to do 
                }
            };
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

1
投票

确保添加以下内容:

if (event.getAction()!=KeyEvent.ACTION_DOWN)
                return true;

在 onKey 代码块中避免事件调用两次。


0
投票

我使用一种方法来更改它具有以下代码的片段

 getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit).replace(R.id.content_frame, mContent, mContent.getClass().getSimpleName()).addToBackStack(null)
                .commit();

对于后退按钮这个 .

@Override
    public void onBackPressed() {
        // note: you can also use 'getSupportFragmentManager()'
        FragmentManager mgr = getSupportFragmentManager();
        if (mgr.getBackStackEntryCount() == 1) {
            // No backstack to pop, so calling super
            finish();
        } else {
            mgr.popBackStack();
        }
    }

要注意的重要一点是我使用 1 来检查 getBackStackEntryCount 这是因为如果你不使用它并使用 0 用户看不到最后一个后退按钮。


0
投票

使用这个(在科特林中)

 activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // in here you can do logic when backPress is clicked
        }
    })

我认为这是最优雅的方式


0
投票

试试这个,它帮助了我:)

 @Override  
    public void onResume() { //Pressed return button - returns to the results menu
        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) {
                    /*Here your code*/
                    return true;
                }
                return false;
            }
        });
    }


0
投票

只需将其粘贴到您的活动主目录中

 @Override
public void onBackPressed() {


    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
        getSupportFragmentManager().popBackStack();
    } else {
        finish();
    }


    
}

0
投票

Fragment Pressing Back Button - 我们正在使用 popBackStack() 函数。

In Kotlin - 在您的活动中编写代码

override fun onBackPressed() {
     super.onBackPressed()
     supportFragmentManager.popBackStack();
}
© www.soinside.com 2019 - 2024. All rights reserved.