BottomNavigationView - 如何避免重新创建片段并重用它们

Arm*_*ian 14 java android android-fragments bottomnavigationview

我想在我的项目中制作一个底部导航栏.每个视图都有自己的片段.问题是,每次我点击按钮更改视图,例如从最近更改为收藏夹,它会创建具有全新状态的新片段(例如滚动位置,文本更改我的片段包含的任何内容).我知道在官方Android文档中有人写道,底部导航栏应该重置任务状态,但我认为这对用户来说太不舒服了.我希望有一些像instagram这样的功能,你可以从feed更改为探索,然后返回到滚动位置,图像缓存一切都保存.我几乎尝试了解决这个问题的方法,唯一有效的方法就是根据情况设置可视性GONE和设置可见性VISIBLE但我明白这不是正确的方式应该有更好的方法这样做我不是在谈论手动保存所需的实例.我几乎每个关于底部导航片段的教程都会遵循,但有趣的是,没有人有兴趣在没有每次调用new的情况下使用它.

在此输入图像描述

在此输入图像描述

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, FirstFragment.newInstance());
fragmentTransaction.commit();

bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;
        switch (item.getItemId()) {
            case R.id.menu_dialer:
                fragment = FirstFragment.newInstance();
                break;
            case R.id.menu_email:
                fragment = SecondFragment.newInstance();
                break;
            case R.id.menu_map:
                fragment = ThirdFragment.newInstance();
                break;
        }
        if (fragment != null) {
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frameLayout, fragment);
            fragmentTransaction.commit();
        }
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

我也试过onAttach和Deattach解决方案,但再次没有成功.

视频链接:新的我试过Nino Handler版本它只在我点击相同的片段按钮时才有效

也许它是连接我使用金丝雀版本或我的gradle依赖项中的错误? 在此输入图像描述

最新消息:

最新消息:

public class MainActivity extends AppCompatActivity {

    private TextView mTextMessage;


    private static final String TAG_FRAGMENT_ONE = "fragment_one";
    private static final String TAG_FRAGMENT_TWO = "fragment_two";

    private FragmentManager fragmentManager;
    private Fragment currentFragment;

    String TAG = "babken";
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        Fragment fragment = null;
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                   fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
                    if (fragment == null) {
                        fragment = FragmentFirst.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_ONE);

                    break;
                case R.id.navigation_dashboard:

                     fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO);
                    if (fragment == null) {
                        fragment = FragmentSecond.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_TWO);

                    break;
            }
            return true;

        }
    };

    private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) {
        if (!fragment.equals(currentFragment)) {
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.armen, fragment, tag)
                    .commit();
            currentFragment = fragment;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
        if (fragment == null) {
            fragment = FragmentFirst.newInstance();
        }
        replaceFragment(fragment, TAG_FRAGMENT_ONE);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

}
Run Code Online (Sandbox Code Playgroud)

Buk*_*mi 20

我有类似的问题,但这段代码解决了我的问题.

public class MainActivity extends AppCompatActivity {

final Fragment fragment1 = new HomeFragment();
final Fragment fragment2 = new DashboardFragment();
final Fragment fragment3 = new NotificationsFragment();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

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

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


    BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    fm.beginTransaction().add(R.id.main_container, fragment3, "3").hide(fragment3).commit();
    fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
    fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();

}


private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.navigation_home:
                fm.beginTransaction().hide(active).show(fragment1).commit();
                active = fragment1;
                return true;

            case R.id.navigation_dashboard:
                fm.beginTransaction().hide(active).show(fragment2).commit();
                active = fragment2;
                return true;

            case R.id.navigation_notifications:
                fm.beginTransaction().hide(active).show(fragment3).commit();
                active = fragment3;
                return true;
        }
        return false;
    }
};
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

来源:BottomNavigationView With Fragments(无片段娱乐).

  • 这个答案是***错误***。如果不首先尝试使用“findFragmentByTag”获取片段,则不能假设创建片段的新实例。这将在进程死亡后中断。 (2认同)

luc*_*ler 5

我不会全局保留片段实例。而是在创建片段时向片段添加标签

getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, new PlaceholderFragment(), TAG_PLACEHOLDER)
            .commit();
Run Code Online (Sandbox Code Playgroud)

然后你总是可以像这样检索它:

Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_PLACEHOLDER);
    if (fragment == null) {
        fragment = new PlaceholderFragment();
    }
    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, fragment, TAG_PLACEHOLDER)
            .commit();
Run Code Online (Sandbox Code Playgroud)

更新:我更新了我的答案并提供了一个完整的解决方案:

private static final String TAG_FRAGMENT_ONE = "fragment_one";
private static final String TAG_FRAGMENT_TWO = "fragment_two";
private static final String TAG_FRAGMENT_THREE = "fragment_three";

private FragmentManager fragmentManager;
private Fragment currentFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // instantiate the fragment manager
    fragmentManager = getSupportFragmentManager();

    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
    if (fragment == null) {
        fragment = FirstFragment.newInstance();
    }
    replaceFragment(fragment, TAG_FRAGMENT_ONE);

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            Fragment fragment = null;
            switch (item.getItemId()) {
                case R.id.menu_dialer:
                    // I'm aware that this code can be optimized by a method which accepts a class definition and returns the proper fragment
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
                    if (fragment == null) {
                        fragment = FirstFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_ONE);
                    break;
                case R.id.menu_email:
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO);
                    if (fragment == null) {
                        fragment = SecondFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_TWO);
                    break;
                case R.id.menu_map:
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_THREE);
                    if (fragment == null) {
                        fragment = ThirdFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_THREE);
                    break;
            }
            return true;
        }
    });
}

private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) {
    if (!fragment.equals(currentFragment)) {
        fragmentManager
            .beginTransaction()
            .replace(R.id.frameLayout, fragment, tag)
            .commit();
        currentFragment = fragment;
    }
}
Run Code Online (Sandbox Code Playgroud)

附加信息:如果您想确保片段状态不会改变,并且如果您还希望能够滑动片段,您应该考虑使用带有FragmentStatePagerAdapterViewPager并在每次单击事件时更改适配器中的当前片段