簡體   English   中英

帶有片段的操作欄向上導航

[英]actionbar up navigation with fragments

我有一個選項卡式 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。 如何使用操作欄向上按鈕實現此功能?

實現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;
}

我知道了。 只需覆蓋托管活動中的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()如下面的答案所述。

如果您有一個父活動並希望此向上按鈕用作后退按鈕,則可以使用以下代碼:

將其添加到主活動類中的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;
     ....
 }

我一直都在使用這個,看起來非常合法

你可以像按鈕一樣按下按鈕;

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

我知道這個問題很老,但可能有人(像我一樣)也需要它。

如果您的Activity擴展了AppCompatActivity ,您可以使用更簡單的(兩步)解決方案:

1 - 每次添加非主片段時,只需在提交片段事務后立即顯示向上按鈕。 像這樣:

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

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

2 - 然后按下UP按鈕時,將其隱藏。

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

而已。

我使用了Roger Garzon Nietosohailaziz的答案組合。 我的應用程序只有一個MainActivity,以及加載到其中的片段A,B,C。 我的“home”片段(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();
    }
}

fragmentB,fragmentC:

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

    // other fragment init stuff
    ...
}

科特林:

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 }

    ...
}

這對我有用。 例如,覆蓋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)

單擊它可以返回上一個活動。

這是一個非常好的和可靠的解決方案: 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;
    }
}

如果這個活動有一個空的片段堆棧,你想回到你以前的活動:

如果您有一個 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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM