【问题标题】:Switch between Fragments in BottomNavigationView在 BottomNavigationView 中的 Fragment 之间切换
【发布时间】:2017-06-08 00:54:42
【问题描述】:

我正在使用带有底部导航视图的简单应用程序。我有 3 个片段(布局和 java)。我有 BottonNavigationView,在 MainActivity.java 中声明。我的底部导航有 3 个项目,用于 3 个片段。所以,在我的 MainActivity.java 中,当我选择一个项目时,它会启动一个片段。因此,当我再次选择另一个项目时,什么也没有发生,因为在 java 片段中我需要声明 BottonNavigationView,但我不知道如何设置它以将实际片段与另一个片段切换。 我试过这个链接,但没有成功:https://developer.android.com/training/basics/fragments/fragment-ui.html

对不起,我的英语不好

代码如下:

主要活动

 @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    Fragment selectedFragment = null;
    switch (item.getItemId()) {
        case R.id.navigation_home:
            selectedFragment = HomeFragment.newInstance();
            break;
        case R.id.navigation_dashboard:
            selectedFragment = DashboardFragment.newInstance();
            break;
        case R.id.navigation_notifications:
            selectedFragment = NotificationsFragment.newInstance();
            break;
    }
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.content, selectedFragment);
    transaction.commit();
    return true;
}

片段 Java 示例

public class HomeFragment extends Fragment {
public static HomeFragment newInstance() {
HomeFragment fragment = new HomeFragment();
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.navigation_home, container, false);
return inflater.inflate(R.layout.navigation_home, container, false);
}

【问题讨论】:

  • 为什么你总是创建新实例?
  • 在我的 main_activity 布局中,我有一个带有 FrameLayout 和 BottomNavigationView 的线性布局,我想我需要创建一个新实例,不是吗?
  • 您可以只创建一次片段,然后可以再次使用它们。
  • 你能给我一个代码吗?以及我将如何在所选项目的片段之间切换?
  • 例如Fragment homeFragment = HomeFragment.newInstance();片段通知Fragment = NotificationsFragment.newInstance();在 switch 情况下,您可以设置 selectedFragment = homeFragment 或其他内容

标签: android android-fragments bottomnavigationview


【解决方案1】:

你可以试试:

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    Fragment selectedFragment = null;
    switch (item.getItemId()) {
        case R.id.navigation_home:
            selectedFragment = HomeFragment.newInstance();
            break;
        case R.id.navigation_dashboard:
            selectedFragment = DashboardFragment.newInstance();
            break;
        case R.id.navigation_notifications:
            selectedFragment = NotificationsFragment.newInstance();
            break;
    }
    getSupportFragmentManager().beginTransaction().replace(R.id.content, selectedFragment).commit();
    return true;
}

【讨论】:

  • 哇,看起来正在工作,谢谢。还有一个问题:我有三个片段(主页、仪表板和通知)。 Home 片段是我的应用程序的主菜单。所以,如果我在仪表板或通知中,并且我按下按钮,我想将 onKeyDown 设置为返回主页片段,并且在主页片段中,如果我按下返回按钮,我想关闭 de 应用程序。你知道怎么做吗?
  • 如果你想在 Fragment 之间转换,调用 addToBackStack()。 stackoverflow.com/questions/7992216/…
  • 谢谢@Thien,代码很多,但我会尝试。谢谢
  • @ThienHuynh 第一次运行时如何设置片段?
  • @RazorHead navigationView.getMenu().getItem(0).setChecked(true);项目 0 表示 HomeFragment 是第一个。
【解决方案2】:

您不必每次都创建 newInstance。您可以保存片段状态。请点击以下链接

fragmentManager.beginTransaction().hide(toBeHidden).show(toBeShown).commit();

https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711

【讨论】:

    【解决方案3】:

    在这种情况下,最好尝试从fragmentManager 获取存在片段,例如fragmentManager.findFragmentByTag(tag)。您可以更流畅地切换,并且您不需要从网络加载一些内容(如果您在片段或片段的演示者中有这样的代码)

    【讨论】:

      【解决方案4】:

      您应该从每个片段创建一次 newIstance。稍后您可以隐藏活动片段,然后显示新片段。

          Fragment activeFragment;
          ArrayList<Fragment> fragment;
      
      public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                  Fragment selectedFragment = null;
                  switch (item.getItemId()) {
                      case R.id.navigation_fragment:
                          selectedFragment = ShowMyFragment.newInstance();
                          replaceFragment(selectedFragment);
                          return true;
      }
      });
          private void replaceFragment(Fragment selectedFragment) {
              boolean lastOpened = false;
              for ( int i=0; i<fragment.size();i++ )
              {
                  if ( fragment.get(i) == selectedFragment ) {
                      lastOpened = true;
                      break;
                  }
              }
              if (!lastOpened) {
                  getSupportFragmentManager().beginTransaction().replace(R.id.content, selectedFragment).commit();
              }
              else
              {
                  getSupportFragmentManager().beginTransaction().hide(activeFragment).show(selectedFragment).commit();
              }
      
              activeFragment = selectedFragment;
          }
      

      【讨论】:

      • 如果您在片段中更改工具栏,则无法正常工作。屏幕旋转工具栏菜单覆盖后
      【解决方案5】:

      只是在 onCreate 中添加一个像这样的空白实现 bottomNavView.setOnNavigationItemReselectedListener {}

      【讨论】:

        【解决方案6】:

        我的完整解决方案,我认为对后辈有用:

        所以,我们有 MainActivity:

        import android.os.Bundle
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        import androidx.fragment.app.Fragment
        
        class MainMenuActivity : AppCompatActivity() {
        
        override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
        
          val bottomNav: BottomNavigationView = findViewById(R.id.bottom_naviagtion)
          bottomNav.setOnNavigationItemSelectedListener(navListener)
        
            if (savedInstanceState == null) {
                 supportFragmentManager.beginTransaction().replace(
                      R.id.fragment_container,
                     HomeFragment()
                 ).commit()
             }
         }
        
         private val navListener: BottomNavigationView.OnNavigationItemSelectedListener =
              BottomNavigationView.OnNavigationItemSelectedListener { item ->
                 var selectedFragment: Fragment? = null
                 when (item.itemId) {
                R.id.bottom_home -> selectedFragment =
                    HomeFragment()
                R.id.bottom_events -> selectedFragment =
                    EventFragment()
                R.id.bottom_contacts -> selectedFragment =
                    ContactsFragment()
                R.id.bottom_menu -> selectedFragment =
                    MenuFragment()
            }
            supportFragmentManager.beginTransaction().replace(
                R.id.fragment_container,
                selectedFragment!!
             ).commit()
             true
         }
        }
        

        activity_main.xml:

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@id/bottom_naviagtion"/>
        
        <View
            android:layout_width="match_parent"
            android:layout_height="10dp"
            android:layout_above="@id/bottom_naviagtion"
            android:background="@drawable/shadow"/>
        
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_naviagtion"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            app:menu="@menu/bottom_menu"
            android:background="?android:attr/windowBackground" />
        
        </RelativeLayout>
        

        每个片段类看起来像:

        import android.os.Bundle
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        import androidx.fragment.app.Fragment
        
        class HomeFragment : Fragment() {
           override fun onCreateView(
               inflater: LayoutInflater,
               container: ViewGroup?,
               savedInstanceState: Bundle?
           ): View? {
               return inflater.inflate(R.layout.fragment_home, container, false)
           }
         }
        

        HomeFragment (fragment_home.xml) 的.xml 文件看起来像(其他片段看起来一样):

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/home"
            android:textSize="30sp"
            android:layout_centerInParent="true"/>
        
        </RelativeLayout>
        

        NavigationBottomMenu .xml 看起来(bottom_menu.xml):

        <?xml version="1.0" encoding="utf-8"?>
        <menu
        xmlns:android="http://schemas.android.com/apk/res/android">
        
        <item
            android:id="@+id/bottom_home"
            android:icon="@drawable/home_selector"
            android:title="Home" />
        
        
        <item
            android:id="@+id/bottom_events"
            android:icon="@drawable/events_selector"
            android:title="Events" />
        
        <item
            android:id="@+id/bottom_contacts"
            android:icon="@drawable/contacts_selector"
            android:title="Contacts"/>
        
        <item
            android:id="@+id/bottom_menu"
            android:icon="@drawable/menu_selector"
            android:title="Menu" />
        
        </menu>
        

        drawble 文件夹中使用的图标像 Vector Asset 一样被导入

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-19
          • 2016-12-21
          • 2014-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多