94

我有一个选项卡式 Actionbar/viewpager 布局,其中包含三个选项卡ABC。在选项卡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 中,当我按下硬件(电话)后退按钮时,我返回到原始选项卡式(ABC)布局并选择了 CFragment。如何使用操作栏向上按钮实现此功能?

4

10 回答 10

190

实现OnBackStackChangedListener此代码并将其添加到您的 Fragment Activity。

@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;
}
于 2013-12-01T16:45:01.597 回答
43

我得到了它。只需在托管活动中覆盖onOptionsItemSelected并弹出后台堆栈,例如

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home: {
            FragmentManager fm = getSupportFragmentManager();
            if (fm.getBackStackEntryCount() > 0) {
                fm.popBackStack();
                return true;
            }
            break;
        }
    }
    return super.onOptionsItemSelected(item);
}

致电getActionBar().setDisplayHomeAsUpEnabled(boolean);并按以下答案中的说明进行getActionBar().setHomeButtonEnabled(boolean);onBackStackChanged()

于 2012-10-31T18:48:07.337 回答
18

如果您有一个父活动并希望此向上按钮用作后退按钮,则可以使用以下代码:

将此添加到主活动类中的 onCreate

getSupportFragmentManager().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;
     ....
 }

我通常一直都在使用它,而且看起来很合法

于 2014-07-22T03:31:01.910 回答
11

您可以使用向上按钮(如后退按钮)返回;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}
于 2015-05-23T16:29:29.310 回答
8

我结合了Roger Garzon Nietosohailaziz 的答案。我的应用程序有一个 MainActivity,以及加载到其中的片段 A、B、C。我的“家”片段(A)实现了 OnBackStackChangedListener,并检查了 backStack 的大小;如果小于 1,则隐藏 UP 按钮。片段 B 和 C 总是加载返回按钮(在我的设计中,B 从 A 启动,C 从 B 启动)。MainActivity 本身只是在 UP 按钮点击时弹出 backstack,并具有显示/隐藏按钮的方法,片段调用:

主要活动:

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

片段B,片段C:

public void onCreate(Bundle savedinstanceSate) {
    // show the UP button
    ((MainActivity)getActivity()).showUpButton();

    // other fragment init stuff
    ...
}
于 2015-09-15T15:55:21.847 回答
8

我知道这个问题很老,但可能有人(像我一样)也需要它。

如果您的 Activity 扩展AppCompatActivity,您可以使用更简单的(两步)解决方案:

1 - 每当您添加非主页片段时,只需在提交片段事务后立即显示向上按钮。像这样:

    // ... add a fragment
    // Commit the transaction
    transaction.commit();

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

2 - 然后当按下向上按钮时,将其隐藏。

@Override
public boolean onSupportNavigateUp() {
    getSupportActionBar().setDisplayHomeAsUpEnabled(false);        
    return true;
}

就是这样。

于 2016-06-05T19:56:41.410 回答
5

这对我有用。覆盖 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)

单击它会带您返回上一个活动。

于 2016-10-31T13:14:24.417 回答
5

科特林:

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 }

    ...
}
于 2018-01-29T17:11:37.100 回答
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;
    }
}
于 2015-01-03T11:34:22.350 回答
0

如果这个活动有一个空的片段堆栈,你想回到你以前的活动:

如果您有一个 MainActivity 并且您正在导航到例如带有嵌套的prefernceScreens 的 SettingsActivity,这可能会很有用。NavigateUp 将弹出片段,直到您可以完成 SettingsActivity 以返回 parentActivity/root。

/**
 * On actionbar up-button popping fragments from stack until it is empty.
 * @return true if fragment popped or returned to parent activity successfully.
 */
@Override
public boolean onSupportNavigateUp() {
    //Pop back stack if the up button is pressed.
    boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0;
    if (canGoBack) {
        getSupportFragmentManager().popBackStack();
    } else {
        finish();
        return super.onSupportNavigateUp();
    }
    return true;
}

注意: setDisplayHomeAsUpEnabled(true);在片段活动中onCreate()

于 2022-01-15T20:25:24.357 回答