Android 带片段的actionbar向上导航

Android 带片段的actionbar向上导航,android,android-fragments,android-actionbar,Android,Android Fragments,Android Actionbar,我有一个选项卡式的Actionbar/viewpager布局,有三个选项卡,分别是a、B和C。在tabCtab(fragment)中,我添加了另一个片段,比如fragmentD。与 DFragment f= new DFragment(); ft.add(android.R.id.content, f, ""); ft.remove(CFragment.this); ft.addToBackStack(null); ft.commit(); 我修改了DfFragment的onResu

我有一个选项卡式的Actionbar/viewpager布局,有三个选项卡,分别是aBC。在tabCtab(fragment)中,我添加了另一个片段,比如fragmentD。与

 DFragment f= new DFragment();
 ft.add(android.R.id.content, f, "");
 ft.remove(CFragment.this);
 ft.addToBackStack(null);
 ft.commit();
我修改了DfFragment的onResume中的actionbar以添加按钮:

ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);

现在在DFragment中,当我按下hardware(phone)Back按钮时,我将返回到选择了CFragment的原始选项卡(ABC)布局。如何使用actionbar up按钮实现此功能?

我知道了。只需覆盖托管活动中的onOptionsItemSelected,并弹出backbackback,例如

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(布尔值)
getActionBar().setHomeButtonEnabled(布尔值)
onbackbackchanged()
中,如下面的回答所述。

实现
onbackbackbackchangedListener
并将此代码添加到片段活动中

@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;
}

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

将其添加到主活动类中的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);
            }
        }

    });
然后添加选项ItemSelected,如下所示:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
     ....
 }

我通常一直都在使用它,而且似乎非常合法

这是一个非常好且可靠的解决方案:

这个家伙制作了一个抽象片段来处理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;
    }
}

您可以像后退按钮一样使用向上按钮返回

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}
我使用了和答案的组合。我的应用程序只有一个MainActivity和加载到其中的片段a、B、C。我的“主”片段(A)实现OnBackbackChangedListener,并检查Backbackback的大小;如果小于1,则隐藏向上按钮。片段B和C总是加载后退按钮(在我的设计中,B从A启动,C从B启动)。MainActivity本身只是在点击按钮时弹出backbackback,并具有显示/隐藏按钮的方法,片段调用该按钮:

main活动:

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); }
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();
    }
}
public void onCreate(Bundle savedinstanceSate) {
    // show the UP button
    ((MainActivity)getActivity()).showUpButton();

    // other fragment init stuff
    ...
}
fragmentA(实现FragmentManager.onbackbackchangedListener):

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); }
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();
    }
}
public void onCreate(Bundle savedinstanceSate) {
    // show the UP button
    ((MainActivity)getActivity()).showUpButton();

    // other fragment init stuff
    ...
}

我知道这个问题由来已久,但可能有人(像我一样)也需要它

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

1-无论何时添加非主片段,只要在提交片段事务之后显示up按钮即可。像这样:

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

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2-然后当按下“向上”按钮时,将其隐藏

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

就这样。

这对我很有效。覆盖onSupportNavigateUp和onBackPressed,例如(Kotlin中的代码)

现在在片段中,如果显示向上箭头

activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
单击它将返回上一个活动。

Kotlin:

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 }

    ...
}
类MyActivity:AppCompatActivity(){
重写创建时的乐趣(savedInstanceState:Bundle?){
...
supportFragmentManager.AddOnBackbackChangedListener{setupHomeAsUp()}
setupHomeAsUp()
}
私人娱乐设置HomeAsup(){
val shouldShow=0
您还必须调用getActivity().getActionBar().setDisplayHomeAsUpEnabled(false);要在弹出后堆栈后移除向上按钮,这不是正确的方法。它保持向上按钮处于启用状态。您应该将该代码放入带有case
android.R.id.home
switch
语句中。关于
onSupportNavigateUp()
,“方法不会从其超类重写方法”。如果您已经选择了
onoptionItem
,还可以检查itemId
android.R.id.home
而不是添加
onSupportNavigateUp
。如果API版本>=14,则使用onNavigateUp而不是onSupportNavigateUp@Override公共布尔值onNavigateUp(){//当按下向上按钮时调用此方法。只调用弹出堆栈。getFragmentManager().popBackStack();返回true;}是否应该在
操作栏中的应用程序图标旁边显示一个向上插入符号?
?我在执行此代码时没有看到。我只能单击图标,但它没有任何作用。Android 4.0+。如果OnBackbackChanged()不要覆盖,请确保您的活动实现FragmentManager.OnBackbackChangedListener接口。虽然此链接可以回答问题,但最好包含答案的基本部分并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效。顺便说一句:如果您发现重复,请se将它们标记为这样。thx.在onStart中设置SelectedFragment是否重要?我在我的
活动
中尝试准确地使用此代码,希望它会返回到它开始的片段。当我转到我的
活动
时,后退按钮出现在我的应用程序图标附近,但我单击图标,什么也没有发生(应该返回到片段)。知道为什么吗?谢谢。@Daniel您的代码是合法的。它确实有效。您可能只想使用try-catch选项对其进行排序,以防万一。您知道如何防止任何不可预见的异常和应用crashing@NoniA.这只会返回到以前的片段(例如,片段B->片段a),如果您在新活动中膨胀1个片段,则不会返回到以前的活动。可能重复