我有一个带标签的Actionbar / viewpager布局,其中有三个标签,分别为 A , B 和 C 。在标签 C 标签(片段)中,我要添加另一个片段,例如片段 D 。与
DFragment f= new DFragment();
ft.add(android.R.id.content, f, "");
ft.remove(CFragment.this);
ft.addToBackStack(null);
ft.commit();
我修改了DFragment的onResume中的操作栏以添加按钮:
ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
现在在DFragment中,当我按下硬件(手机)后退按钮时,我返回到选择了CFragment的原始选项卡(ABC)布局。如何通过操作栏按钮实现此功能?
答案 0 :(得分:180)
实施OnBackStackChangedListener
并将此代码添加到您的片段活动中。
@Override
public void onCreate(Bundle savedInstanceState) {
//Listen for changes in the back stack
getSupportFragmentManager().addOnBackStackChangedListener(this);
//Handle when activity is recreated like on orientation Change
shouldDisplayHomeUp();
}
@Override
public void onBackStackChanged() {
shouldDisplayHomeUp();
}
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0;
getSupportActionBar().setDisplayHomeAsUpEnabled(canGoBack);
}
@Override
public boolean onSupportNavigateUp() {
//This method is called when the up button is pressed. Just the pop back stack.
getSupportFragmentManager().popBackStack();
return true;
}
答案 1 :(得分:37)
我明白了。只需覆盖托管活动中的 onOptionsItemSelected 并弹出backstack,例如
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}
return true;
default:
return super.onOptionsItemSelected(item);;
}
}
按照以下答案中的说明,在getActionBar().setDisplayHomeAsUpEnabled(boolean);
中致电getActionBar().setHomeButtonEnabled(boolean);
和onBackStackChanged()
。
答案 2 :(得分:18)
如果您有一个父活动并希望此向上按钮用作后退按钮,则可以使用此代码:
将此添加到主要活动类
中的onCreategetSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
}
}
});
然后像这样添加onOptionsItemSelected:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getSupportFragmentManager().popBackStack();
return true;
....
}
我通常一直使用这个并且看起来非常合法
答案 3 :(得分:10)
您可以使用向上按钮返回按钮;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
答案 4 :(得分:8)
我知道这个问题很老,但可能有人(像我一样)也需要它。
如果您的活动扩展 AppCompatActivity ,您可以使用更简单的(两步)解决方案:
1 - 每次添加非主页片段时,只需在提交片段事务后立即显示向上按钮。像这样:
// ... add a fragment
// Commit the transaction
transaction.commit();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2 - 然后按下UP按钮时,隐藏它。
@Override
public boolean onSupportNavigateUp() {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
return true;
}
那就是它。
答案 5 :(得分:6)
我使用了Roger Garzon Nieto's和sohailaziz's个答案的组合。我的应用程序只有一个MainActivity,以及加载到其中的片段A,B,C。我的家#34; fragment(A)实现OnBackStackChangedListener,并检查backStack的大小;如果它小于1,则它会隐藏UP按钮。片段B和C总是加载后退按钮(在我的设计中,B从A启动,C从B启动)。 MainActivity本身只是在UP按钮点击时弹出Backstack,并有方法显示/隐藏片段调用的按钮:
<强> MainActivity:强>
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }
fragmentA(实现FragmentManager.OnBackStackChangedListener):
public void onCreate(Bundle savedinstanceSate) {
// listen to backstack changes
getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this);
// other fragment init stuff
...
}
public void onBackStackChanged() {
// enable Up button only if there are entries on the backstack
if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) {
((MainActivity)getActivity()).hideUpButton();
}
}
fragmentB,fragmentC:
public void onCreate(Bundle savedinstanceSate) {
// show the UP button
((MainActivity)getActivity()).showUpButton();
// other fragment init stuff
...
}
答案 6 :(得分:4)
这对我有用。例如,覆盖onSupportNavigateUp和onBackPressed(Kotlin中的代码);
override fun onBackPressed() {
val count = supportFragmentManager.backStackEntryCount
if (count == 0) {
super.onBackPressed()
} else {
supportFragmentManager.popBackStack()
}
}
override fun onSupportNavigateUp(): Boolean {
super.onSupportNavigateUp()
onBackPressed()
return true
}
现在在片段中,如果您显示向上箭头
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
点击它会带您回到之前的活动。
答案 7 :(得分:3)
科特林:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() }
setupHomeAsUp()
}
private fun setupHomeAsUp() {
val shouldShow = 0 < supportFragmentManager.backStackEntryCount
supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow)
}
override fun onSupportNavigateUp(): Boolean =
supportFragmentManager.popBackStack().run { true }
...
}
答案 8 :(得分:2)
这是一个非常好且可靠的解决方案:http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/
这家伙制作了一个抽象片段来处理backPress行为,并使用策略模式在活动片段之间切换。
对于你们中的一些人来说,抽象类可能有一点缺点......
很快,链接的解决方案如下:
// Abstract Fragment handling the back presses
public abstract class BackHandledFragment extends Fragment {
protected BackHandlerInterface backHandlerInterface;
public abstract String getTagText();
public abstract boolean onBackPressed();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!(getActivity() instanceof BackHandlerInterface)) {
throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
} else {
backHandlerInterface = (BackHandlerInterface) getActivity();
}
}
@Override
public void onStart() {
super.onStart();
// Mark this fragment as the selected Fragment.
backHandlerInterface.setSelectedFragment(this);
}
public interface BackHandlerInterface {
public void setSelectedFragment(BackHandledFragment backHandledFragment);
}
}
活动中的用法:
// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS
// IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment
public class TheActivity extends FragmentActivity implements BackHandlerInterface {
private BackHandledFragment selectedFragment;
@Override
public void onBackPressed() {
if(selectedFragment == null || !selectedFragment.onBackPressed()) {
// Selected fragment did not consume the back press event.
super.onBackPressed();
}
}
@Override
public void setSelectedFragment(BackHandledFragment selectedFragment) {
this.selectedFragment = selectedFragment;
}
}