2012-10-17 17 views
6

Android 4.1 ActionBarは、便利なナビゲーションモードをリストまたはタブとして提供します。ビューandroid.R.id.contentに表示する3つのフラグメントから選択するにはSpinnerAdapterを使用しています。 onNavigationItemSelected()リスナーは、各フラグメントをビューに展開し、FragmentTransaction.addToBackStack(null)を使用してバック・スタックに追加します。フラグメントバックスタックをトラバースするときにActionBarナビゲーション項目をリフレッシュするにはどうすればよいですか?

これはすべて広告として機能しますが、現在のバックスタックを反映するようにActionBarを更新する方法はわかりません。 ActionBar.setSelectedNavigationItem(position)を使用すると、新しいOnNavigationListener()がトリガーされ、別のFragmentTransactionも作成されます(効果はありません)。説明のためにコードを以下に示します。解決策があれば助けてください。


public class CalcActivity extends Activity { 
private String[] mTag = {"calc", "timer", "usage"}; 
private ActionBar actionBar; 

/** An array of strings to populate dropdown list */ 
String[] actions = new String[] { 
    "Calculator", 
    "Timer", 
    "Usage" 
}; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    this.actionBar = getActionBar(); 

    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 
    // may not have room for Title in actionbar 
    actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); 

    actionBar.setListNavigationCallbacks(
    // Specify a SpinnerAdapter to populate the dropdown list. 
    new ArrayAdapter<String>(
     actionBar.getThemedContext(), 
     android.R.layout.simple_list_item_1, 
     android.R.id.text1, 
     actions), 
    // Provide a listener to be called when an item is selected. 
    new NavigationListener() 
    );  
} 

public class NavigationListener implements ActionBar.OnNavigationListener { 
    private Fragment mFragment; 
    private int firstTime = 0; 

    public boolean onNavigationItemSelected(int itemPos, long itemId) { 
     mFragment = getFragmentManager().findFragmentByTag(mTag[itemPos]); 

     if (mFragment == null) { 
      switch (itemPos) { 
      case 0: 
       mFragment = new CalcFragment(); 
       break; 
      case 1: 
       mFragment = new TimerFragment(); 
       break; 
      case 2: 
       mFragment = new UsageFragment(); 
       break; 
      default: 
       return false; 
      }    
      mFragment.setRetainInstance(true); 
     } 

     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     if (firstTime == 0) { 
      firstTime++; 
      ft.add(android.R.id.content, mFragment, mTag[itemPos]); 
     } else { 
      ft.replace(android.R.id.content, mFragment, mTag[itemPos]); 
      ft.addToBackStack(null); 
     } 
     ft.commit(); 

     Toast.makeText(getBaseContext(), "You selected : " + 
       actions[itemPos], Toast.LENGTH_SHORT).show(); 

     return true; 
    }  
} 

public static class CalcFragment extends Fragment {    
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_calc, container, false); 
    return v; 
    } 
} 

public static class TimerFragment extends Fragment { 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_timer, container, false); 
    return v; 
    } 
} 

public static class UsageFragment extends Fragment { 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_usage, container, false); 
    return v; 
    } 
} 

答えて

4

あなたはこのような何か行うことができます:

private boolean mListIsNavigatingBack = false; 
    1. あなたは戻るボタンに基づいて、ナビゲーション項目を選択する際に追跡するブール値を作成しますonBackPressedをオーバーライドします。オーバーライドでは、バックスタックにアイテムがあるかどうかを確認します。スーパークラスを呼び出さない場合は、自分自身を処理します。 :

      public void onBackPressed() { 
          if(getFragmentManager().getBackStackEntryCount() > 0){ 
           mListIsNavigatingBack = true; 
      
           //You need to get the previous index in the backstack through some means 
           //possibly by storing it in a stack 
           int previousNavigationItem = ???; 
      
           getActionBar().setSelectedNavigationItem(previousNavigationItem); 
          } 
          else{ 
           super.onBackPressed(); 
          } 
      } 
      
    2. インサイドNavigationListener、バックスタックおよび未設定の状態をポップ手動で、mListIsNavigatingBack状態を取り扱う:

      if(mListIsNavigatingBack){ 
          if(fm.getBackStackEntryCount() > 0){ 
           fm.popBackStack(); 
          } 
          mListIsNavigatingBack = false; 
      } 
      
  • +0

    は、私は、スタックを実装ご提案をいただき、ありがとうございます。さらに複雑さとユニークなUXが与えられたので、私はこのデザインパターンについてもう一度考えています。 ActionBarナビゲーションを使用するときはaddToBackStack()を使用しない方が良いでしょうか? – GregM

    +0

    リストのナビゲーションが複雑になります。通常、バックスタックは、現在のビュー内でフラグメントを交換するためにより多く使用されるため、バックグラウンドにあるフラグメントを再接続するだけでユースケースを単純化できます。 –

    関連する問題