简体   繁体   English

在底部导航栏中保存片段 state

[英]save fragment state in a bottom navigation bar

I have an activity, which basically is a navigation bottom bar containing fragments.我有一个活动,它基本上是一个包含片段的导航底部栏。 If the the user is logged in, the bottom navigation shows 4 fragments: market, favorite, upload and profile.如果用户已登录,底部导航显示 4 个片段:市场、收藏夹、上传和个人资料。 If the user is a guest, there are two fragments: market and login.如果用户是访客,则有两个片段:市场和登录。

Before, every time someone swapped from a fragment to another, it was generated again.以前,每次有人从一个片段交换到另一个片段时,它都会再次生成。 However, I wanted to conserve the state of the fragment, so if someone applied a filter in the market and came back, it had to keep the filter applied.但是,我想保留片段的 state,所以如果有人在市场上应用了过滤器并回来,它必须保持过滤器应用。 I tried implementing this solution https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711 but I feel is not the best so far.我尝试实施此解决方案https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711但我觉得到目前为止还不是最好的。

The code of the nav activity is:导航活动的代码是:

public class NavigationActivity extends AppCompatActivity {

    final Fragment market= new MarketFragment();
    final Fragment favorite = new FavoriteFragment();
    final Fragment updateProduct = new AddProductFragment();
    final Fragment userProfile = new UserProfileFragment();
    final Fragment loginregister = new LoginOrRegisterFragment();
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active = market;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(UnipopApp.usuariLoggejat.getUserLogged() != null){
            setContentView(R.layout.main);
        }
        else{
            setContentView(R.layout.main_guest);
        }
        setUpNavigation();
    }

    public void setUpNavigation() {
        BottomNavigationView bottomNavigationView;
        if(UnipopApp.usuariLoggejat.getUserLogged() != null) {
            bottomNavigationView = findViewById(R.id.bottom_navigation);
            bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavegationItemSelectedListener);
            fm.beginTransaction().add(R.id.nav_host_fragment, favorite, "2").hide(favorite).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, updateProduct, "3").hide(updateProduct).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, userProfile, "5").hide(userProfile).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, market, "1").commit();
        }
        else {
            bottomNavigationView = findViewById(R.id.bottom_navigation_guest);
            bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavegationItemSelectedListener);
            fm.beginTransaction().add(R.id.nav_host_fragment_guest, loginregister, "6").hide(loginregister).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment_guest, market, "1").commit();
        }
    }

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavegationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.action_home:
                    fm.beginTransaction().hide(active).show(market).commit();
                    active = market;
                    return true;
                case R.id.action_favorites:
                    fm.beginTransaction().hide(active).show(favorite).commit();
                    active = favorite;
                    return true;
                case R.id.addProduct_fragment:
                    fm.beginTransaction().hide(active).show(updateProduct).commit();
                    active = updateProduct;
                    return true;
                case R.id.action_user_profile:
                    fm.beginTransaction().hide(active).show(userProfile).commit();
                    active = userProfile;
                    return true;
                case R.id.action_user_profile_guest:
                    fm.beginTransaction().hide(active).show(loginregister).commit();
                    active = loginregister;
                    return true;
            }
            return false;
        }
    };
}

It works but I had to delete the nav graph... However, the thing is that when someone marks a product as favorite in the market and moves to the favorite fragment, it does not appear.它有效,但我不得不删除导航图......但是,问题是当有人将产品标记为市场上的最爱并移动到最喜欢的片段时,它不会出现。 Obviously, it just shows up the fragment again, it does not generate it back with the call from the server.显然,它只是再次显示片段,它不会通过来自服务器的调用生成它。

I am looking for other options because I don't like this solution.我正在寻找其他选择,因为我不喜欢这个解决方案。 If someone can lend me a hand, it would be great.如果有人可以帮我一把,那就太好了。

Thanks谢谢

Recommended solution using Bottom Navigation View and Fragment Navigation.使用底部导航视图和片段导航的推荐解决方案。 Use Activity's SharedViewModel to persist the states of all the navigation fragments.使用Activity 的 SharedViewModel来持久化所有导航片段的状态。

Layout XML (rees/layout/activity_main.xml)布局 XML (rees/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/bottom_navigation_menu" />

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/core_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

Navigation XML (res/navigation/core_navigation.xml)导航 XML (res/navigation/core_navigation.xml)

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/navigation_feed">

<fragment
    android:id="@+id/navigation_home"
    android:name="com.example.HomeFragment"
    android:label="@string/home_title"
    tools:layout="@layout/home_fragment" />

<fragment
    android:id="@+id/navigation_favorites"
    android:name="com.example.FavoritesFragment"
    android:label="@string/favorites_title"
    tools:layout="@layout/favorites_fragment" />

<!--Fill this with other fragments like above-->

</navigation>

Menu XML (res/menu/bottom_navigation_menu.xml)菜单 XML (res/menu/bottom_navigation_menu.xml)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/navigation_home"
    android:enabled="true"
    android:icon="@drawable/ic_home"
    android:title="@string/home_title"/>
<item
    android:id="@+id/navigation_favorites"
    android:enabled="true"
    android:icon="@drawable/ic_favorites"
    android:title="@string/favorites_title"/>

<!--Fill this with other fragments like above-->

</menu>

Activity活动

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupNavigation()
    }

    private fun setupNavigation() {
        val navController = (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
        binding.bottomNavigation.setupWithNavController(navController)
    }
}

You can save filter selection in fragment's viewmodel.您可以将过滤器选择保存在片段的视图模型中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM