2012-10-26 37 views
68

我有三個標籤選項卡式動作條/ viewpager佈局導航說,和Ç。在標籤C tab(片段)中,我添加了另一個片段說片段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。如何通過操作欄向上按鈕來實現此功能?

+0

的可能的複製[?如何實現onBackPressed()的片段(http://stackoverflow.com/questions/5448653/how-to-implement-onbackpressed-in-fragments ) –

回答

157

實施OnBackStackChangedListener並將此代碼添加到您的Fragment活動中。

@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 canback = getSupportFragmentManager().getBackStackEntryCount()>0; 
    getSupportActionBar().setDisplayHomeAsUpEnabled(canback); 
} 

@Override 
public boolean onSupportNavigateUp() { 
    //This method is called when the up button is pressed. Just the pop back stack. 
    getSupportFragmentManager().popBackStack(); 
    return true; 
} 
+16

關於'onSupportNavigateUp()',「方法不會覆蓋超類中的方法」。 – Fred

+0

這個答案比接受的答案更有幫助。非常感謝。 – tinker

+0

謝謝,這比SohailAziz的答案更容易和更清潔! – javaxian

34

我明白了。只是在託管活動中覆蓋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; 
    default: 
     return super.onOptionsItemSelected(item);; 
    } 
} 

呼叫getActionBar().setDisplayHomeAsUpEnabled(boolean);getActionBar().setHomeButtonEnabled(boolean);onBackStackChanged()在下面的答案解釋。

+3

您還必須調用 getActivity()。getActionBar()。setDisplayHomeAsUpEnabled(false); 刪除向上按鈕,一旦你彈出後堆棧 – JoP

+0

這不是正確的方法來做到這一點。它保持啓用向上按鈕。 –

+1

你應該把這段代碼放在'switch'語句中'android.R.id.home'中。 – Fred

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

我一般用這一切的時間似乎很合法

+1

我試着在我的Activity中準確地使用這段代碼,希望它能夠回到它開始的片段。當我進入我的'活動'時,後退按鈕出現在我的應用程序圖標附近,但是我單擊該圖標並沒有任何反應(它應該返回到片段)。任何想法爲什麼?謝謝。 – Azurespot

+1

@Daniel你的代碼是合法的..它確實有效。你只是想嘗試捕捉選項只是incase ..你知道,以防止任何無法預料的例外和應用程序崩潰 – Olu

+1

@NoniA。這隻會返回到前一個片段(例如片段B - >片段A),如果您在新活動中將1個片段充氣,這將不會返回到先前的活動。 –

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; 
    } 
} 
+0

雖然此鏈接可能回答這個問題,但最好包含答案的重要部分[此處](http://meta.stackoverflow.com/a/8259)並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – bummi

+0

好吧,我會看看它。謝謝。 – zatziky

+0

順便說一句:如果你確定重複,請將它們標記爲這樣。謝謝。 – bummi

9

你可以用向上按鈕返回按鈕;

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

簡單而實用 – eren130

4

我用的Roger Garzon Nieto'ssohailaziz's答案的組合。我的應用程序有一個單一的MainActivity,並加載了A,B,C片段。我的「主頁」片段(A)實現了OnBackStackChangedListener,並檢查了backStack的大小;如果小於1,則隱藏UP按鈕。碎片B和C總是加載後退按鈕(在我的設計中,B從A啓動,C從B啓動)。在MainActivity本身只是對持久性有機污染物UP按鈕自來水返回堆棧,並且有方法來顯示/隱藏按鈕,該片段致電:

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 
    ... 
} 
5

我知道這個問題已經老了,但也許是某個人(像我一樣)也需要它。

如果你的活動延伸AppCompatActivity,你可以使用一個簡單(兩步)解決方案:

1 - 只要添加非家庭片段只顯示了按鈕,commiting片段交易之後。像這樣:

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

    getSupportActionBar().setDisplayHomeAsUpEnabled(true); 

2 - 然後當按下UP按鈕時,您將其隱藏。

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

就是這樣。

2

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

點擊它會回到以前的活動。

0

科特林:

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 } 

    ... 
}