1

我正在一個底部導航欄,但我沒有得到完美的底部導航欄。如何處理底部導航完美的背壓

MainActivity類:

public class MainActivity extends AppCompatActivity { 

    private static final String SELECTED_ITEM = "selected_item"; 

    private BottomNavigationView bottomNavigationView; 
    private Toolbar toolbar; 
    private MenuItem menuItemSelected; 
    private int mMenuItemSelected; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation); 
     bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
      @Override 
      public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
       selectFragment(item); 
       return true; 
      } 
     }); 

     //Always load first fragment as default 
     FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     fragmentTransaction.replace(R.id.frameLayout, new AnnouncementFragment()); 
     fragmentTransaction.commit(); 

     if (savedInstanceState != null) { 
      mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0); 
      menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected); 
     } else { 
      menuItemSelected = bottomNavigationView.getMenu().getItem(0); 
     } 

     selectFragment(menuItemSelected); 
    } 

    private void selectFragment(MenuItem item) { 
     Fragment fragment = null; 
     Class fragmentClass; 
     switch (item.getItemId()) { 
      case R.id.action_announcement: 
       fragmentClass = AnnouncementFragment.class; 
       break; 
      case R.id.action_menu: 
       fragmentClass = MenuFragment.class; 
       break; 
      case R.id.action_menu_reports: 
       fragmentClass = ReportFragment.class; 
       break; 
      case R.id.action_setting: 
       fragmentClass = SettingFragment.class; 
       break; 

      default: 
       fragmentClass = AnnouncementFragment.class; 
     } 

     try { 
      fragment = (Fragment) fragmentClass.newInstance(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     FragmentManager fragmentManager = getSupportFragmentManager(); 
     fragmentManager.beginTransaction().replace(R.id.frameLayout, fragment).commit(); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     outState.putInt(SELECTED_ITEM, mMenuItemSelected); 
     super.onSaveInstanceState(outState); 
    } 

而我回壓也不能正常工作:

@Override 
    public void onBackPressed() { 
     MenuItem homeItem = bottomNavigationView.getMenu().getItem(0); 
     if (mMenuItemSelected != homeItem.getItemId()) { 
      selectFragment(homeItem); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

我應該怎麼做,因爲底部菜單有酒吧分佈不均勻。如何正確保持菜單空間不均勻分佈。

在這裏,我附上我的結果,我對AVD First I

獲得Another Selection

+0

什麼是不工作?請描述你正在試圖獲得的行爲以及你實際得到的意外行爲。 – Bryan

+0

On BackPressed工作不正常,當我點擊設置圖標時,圖標之間有足夠的空間 –

+0

您不需要對底部導航欄使用任何自定義設置。 – Tony

回答

3

我昨天有同樣的問題,並實施了一個完全適合我的方法。 幫助別人,我發表了一些要旨在GitHub上: 我創建了一個CustomBottomNavigationView: https://gist.github.com/shrpereira/201380de0a85630a93659549bc3a5f62

在MainActivity,注意configureMenuNavigation方法: https://gist.github.com/shrpereira/7e8d698713614cd85081af59dbd880d2

要完成的例子,這裏是BaseActivity的代碼,它提供了showFragment方法: https://gist.github.com/shrpereira/3fa0e94babb4c75db8d4ce16972ad85f

+0

Awsome,非常非常感謝! +1 –

0

使用addToBackStack方法調用這樣的片段時,

getSupportFragmentManager().beginTransaction().addToBackStack(null).add(R.id.content_home_nav,newFragment).commit(); 

使用此代碼在您的onBackPressed方法

if (getSupportFragmentManager().getBackStackEntryCount() > 0){ 
     getFragmentManager().popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 
0

根據您的要求,您將使用導航碎片進行此操作,您可以使用Tablayout查看尋呼機並進行底部導航。

<android.support.design.widget.TabLayout 
     android:id="@+id/tab_layout" 
     android:layout_width="match_parent" 
     android:layout_height="60dp"></android.support.design.widget.TabLayout> 

,然後用標籤佈局設置viewpager並添加圖標在您的活動tablayout

tabLayout = (TabLayout) findViewById(R.id.tab_layout); 
    viewPager = (ViewPager) findViewById(R.id.controller_pager); 
    viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager())); 
    viewPager.setOffscreenPageLimit(4); 
    tabLayout.setupWithViewPager(viewPager); 
    tabLayout.getTabAt(0).setIcon(R.drawable.selector_home); 
    tabLayout.getTabAt(1).setIcon(R.drawable.selector_contact); 
    tabLayout.getTabAt(2).setIcon(R.drawable.selector_profile); 
    tabLayout.getTabAt(3).setIcon(R.drawable.selector_settings); 

現在處理上tablayout的點擊所有的東西,它會正常工作 tabLayout.addOnTabSelectedListener(本) ;

1

根據該準則爲Material Design

在Android上,後退按鈕不會底 導航欄視圖之間進行導航。

這意味着當我點擊後退按鈕時,應用程序退出,這是默認行爲,例如在Google Photo中。

FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
fragmentTransaction.replace(R.id.content, fragment); 
// note: there is NOT a addToBackStack call 
fragmentTransaction.commit(); 

但谷歌制定規則,然後使用例外!如Google+ ,其中後退按鈕首先導向首頁部分,然後再次按下退出按鈕。

我個人覺得這個「Google+模式」要好得多。

爲了得到它而不會覆蓋onBackPressed您需要確定家庭片段,並從區分這一切其他

navigation = (BottomNavigationView) findViewById(R.id.navigation); 
navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
    @Override 
    public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.navigation_home: 
       viewFragment(new HomeFragment(), FRAGMENT_HOME); 
       return true; 
      case R.id.navigation_page_1: 
       viewFragment(new OneFragment(), FRAGMENT_OTHER); 
       return true; 
      case R.id.navigation_page_2: 
       viewFragment(new TwoFragment(), FRAGMENT_OTHER); 
       return true; 
     } 
     return false; 
    } 
}); 

你有什麼現在要做的就是寫viewfragment方法有:

  1. 知道堆棧中有多少片段之前commit
  2. 如果該片段「家型」,將其保存到堆棧 前commit

  3. 添加OnBackStackChangedListener,當堆減小, (即當我壓回),刪除所有的 「家庭式」的片段(POP_BACK_STACK_INCLUSIVE),使我們的家庭片段

下面的完整方法與評價

private void viewFragment(Fragment fragment, String name){ 
    final FragmentManager fragmentManager = getFragmentManager(); 
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
    fragmentTransaction.replace(R.id.content, fragment); 
    // 1. Know how many fragments there are in the stack 
    final int count = fragmentManager.getBackStackEntryCount(); 
    // 2. If the fragment is **not** "home type", save it to the stack 
    if(name.equals(FRAGMENT_OTHER)) { 
     fragmentTransaction.addToBackStack(name); 
    } 
    // Commit ! 
    fragmentTransaction.commit(); 
    // 3. After the commit, if the fragment is not an "home type" the back stack is changed, triggering the 
    // OnBackStackChanged callback 
    fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { 
     @Override 
     public void onBackStackChanged() { 
      // If the stack decreases it means I clicked the back button 
      if(fragmentManager.getBackStackEntryCount() <= count){ 
       // pop all the fragment and remove the listener 
       fragmentManager.popBackStack(FRAGMENT_OTHER, POP_BACK_STACK_INCLUSIVE); 
       fragmentManager.removeOnBackStackChangedListener(this); 
       // set the home button selected 
       navigation.getMenu().getItem(0).setChecked(true); 
      } 
     } 
    }); 
} 
+0

不起作用。它從來沒有調用onBackStackChanged方法,儘管fragmentTransaction.addtoBackstack(名稱)被稱爲... –

0

我正面臨同樣的問題,但在這樣做後,我得到了解決方案

首先將此代碼粘貼到您的主要活動(您正在使用底部導航欄)

BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation); 
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView); 

,然後創建一個名爲BottomNavigationViewHelper類和粘貼下面的代碼。

public class BottomNavigationViewHelper { 
public static void disableShiftMode(BottomNavigationView view) { 
    BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0); 
    try { 
     Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); 
     shiftingMode.setAccessible(true); 
     shiftingMode.setBoolean(menuView, false); 
     shiftingMode.setAccessible(false); 
     for (int i = 0; i < menuView.getChildCount(); i++) { 
      BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); 
      //noinspection RestrictedApi 
      item.setShiftingMode(false); 
      // set once again checked value, so view will be updated 
      //noinspection RestrictedApi 
      item.setChecked(item.getItemData().isChecked()); 
     } 
    } catch (NoSuchFieldException e) { 
     Log.e("BNVHelper", "Unable to get shift mode field", e); 
    } catch (IllegalAccessException e) { 
     Log.e("BNVHelper", "Unable to change value of shift mode", e); 
    } 
} 

}

希望它有助於

5

試試這個

@Override 
    public void onBackPressed() { 
     BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation); 
     int seletedItemId = bottomNavigationView.getSelectedItemId(); 
     if (R.id.home != seletedItemId) { 
      setHomeItem(MainActivity.this); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

public static void setHomeItem(Activity activity) { 
    BottomNavigationView bottomNavigationView = (BottomNavigationView) 
      activity.findViewById(R.id.navigation); 
    bottomNavigationView.setSelectedItemId(R.id.home); 
} 
0

試試這個。

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { 
     @Override 
     public void onBackStackChanged() { 

      // Gets the previous global stack count 
      int previousStackCount = mPreviousStackCount; 

      // Gets a FragmentManager instance 
      FragmentManager localFragmentManager = getSupportFragmentManager(); 

      // Sets the current back stack count 
      int currentStackCount = localFragmentManager.getBackStackEntryCount(); 

      // Re-sets the global stack count to be the current count 
      mPreviousStackCount = currentStackCount; 

      boolean popping = currentStackCount < previousStackCount; 

      if(popping){ 
       bottomNavigationView.getMenu().getItem(0).setChecked(true); 
      } 

     } 
    }); 
0

請試試這個解決方案。 我對您提供的代碼進行了更改。

我假設在第一次回來時你的應用程序將回到主頁片段(在你的情況下通知片段),如果你再次按下,應用程序將關閉。

此流程也會反映在底部導航欄中。

public class MainActivity extends AppCompatActivity { 
private static final String BACK_STACK_ROOT_TAG = "root_home_fragment"; 
private static final String SELECTED_ITEM = "selected_item"; 
private Fragment fragment; 
private FragmentManager fragmentManager; 
private BottomNavigationView bottomNavigationView; 
private Toolbar toolbar; 
private MenuItem menuItemSelected; 
private int mMenuItemSelected; 
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 
     = new BottomNavigationView.OnNavigationItemSelectedListener() { 

    @Override 
    public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
     boolean selected = false; 
     switch (item.getItemId()) { 
      case R.id.action_announcement: 
       fragment = AnnouncementFragment.newInstance(); 
       selected = true; 
       break; 
      case R.id.action_menu: 
       fragment = MenuFragment.newInstance(); 
       selected = true; 
       break; 
      case R.id.action_menu_reports: 
       fragment = ReportFragment.newInstance(); 
       selected = true; 
       break; 
     case R.id.action_setting: 
     fragment = SettingFragment.newInstance(); 
       selected = true; 

     } 
     if(fragment !=null){ 
      fragmentManager = getFragmentManager(); 
      switch (item.getItemId()) { 
       case R.id.action_announcement: 
        // Pop every fragment from backstack including home fragment. 
        fragmentManager.popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
        fragmentManager.beginTransaction() 
          .replace(R.id.content, fragment) 
          .addToBackStack(BACK_STACK_ROOT_TAG) 
          .commit(); 
        break; 
       default: 

        fragmentManager.beginTransaction() 
          .replace(R.id.content, fragment) 
          .addToBackStack(null) 
          .commit(); 
        break; 
      } 
     } 
     return selected; 
    } 

}; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation); 
    bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 

    //Always load first fragment as default 
    bottomNavigationView.setSelectedItemId(R.id.action_announcement); 

    if (savedInstanceState != null) { 
     mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0); 
     menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected); 
    } else { 
     menuItemSelected = bottomNavigationView.getMenu().getItem(0); 
    } 
} 



@Override 
protected void onSaveInstanceState(Bundle outState) { 
    outState.putInt(SELECTED_ITEM, mMenuItemSelected); 
    super.onSaveInstanceState(outState); 
} 

public void onBackPressed() { 
    int count = getFragmentManager().getBackStackEntryCount(); 
    if(count >1){ 
     // We have lots of fragment on backstack to be popped. 
     // Pop till the root fragment. 
     getFragmentManager().popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
    bottomNavigationView.setSelectedItemId(R.id.action_announcement); 
    } 
    else{ 
     // Close the application when we are on home fragment. 
     supportFinishAfterTransition(); 
    } 
} 
} 
0

這也許有點晚,但我想做到這一點的最好辦法就是如此簡單。

@Override 
public void onBackPressed() { 
    if (mBottomNavigationView.getSelectedItemId() == R.id.action_home) { 
     super.onBackPressed(); 
    } else { 
     mBottomNavigationView.setSelectedItemId(R.id.action_home); 
    } 
} 

我希望它可以幫助和快樂編碼:)

0

onBackPressed並沒有爲我工作。所以我用這個。

@Override 
protected void onResume() { 
    super.onResume(); 
    bottomNavigationView.getMenu().getItem(0).setChecked(true); 
}