BottomNavigationView - 如何避免重新创建 Fragment 并重用它们 [英] BottomNavigationView - How to avoid recreation of Fragments and reuse them

查看:201
本文介绍了BottomNavigationView - 如何避免重新创建 Fragment 并重用它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的项目中制作一个底部导航栏.每个视图都有它自己的片段.问题是,每次我单击按钮更改视图时,例如从最近到收藏夹,它都会创建具有全新状态的新片段(例如滚动位置,无论我的片段包含什么,文本都会更改).我知道在官方的 Android 文档中写到底部导航栏应该重置任务状态,但我认为这对用户来说太不舒服了.我希望有一种类似的功能,例如 Instagram,您可以将其从提要更改为探索,然后再回馈滚动位置,图像缓存的所有内容都保持保存状态.我几乎尝试了所有方法来解决这个问题,唯一有效的方法是根据情况设置可见性 GONE 和设置可见性可见性,但我明白这不是正确的方法,应该有更好的方法来做到这一点,我不是在谈论手动保存所需的实例.我几乎遵循了所有关于底部导航片段的教程,但有趣的是,没有人有兴趣使用它而不每次都调用 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() {@覆盖public boolean onNavigationItemSelected(@NonNull MenuItem item) {片段片段=空;开关(item.getItemId()){案例 R.id.menu_dialer:fragment = FirstFragment.newInstance();休息;案例 R.id.menu_email:fragment = SecondFragment.newInstance();休息;案例R.id.menu_map:fragment = ThirdFragment.newInstance();休息;}如果(片段!= null){FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();fragmentTransaction.replace(R.id.frameLayout, fragment);fragmentTransaction.commit();}返回真;}});

我也尝试了 onAttach 和 Deattach 解决方案,但还是没有成功.

新的更新:

公共类 MainActivity 扩展 AppCompatActivity {私有 TextView mTextMessage;私有静态最终字符串 TAG_FRAGMENT_ONE = "fragment_one";私有静态最终字符串 TAG_FRAGMENT_TWO = "fragment_two";私有 FragmentManager fragmentManager;私有片段 currentFragment;String TAG = "babken";private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener= new BottomNavigationView.OnNavigationItemSelectedListener() {片段片段=空;@覆盖public boolean onNavigationItemSelected(@NonNull MenuItem item) {开关(item.getItemId()){案例 R.id.navigation_home:fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);如果(片段==空){fragment = FragmentFirst.newInstance();}替换片段(片段,TAG_FRAGMENT_ONE);休息;案例 R.id.navigation_dashboard:fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO);如果(片段==空){片段 = FragmentSecond.newInstance();}替换片段(片段,TAG_FRAGMENT_TWO);休息;}返回真;}};private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) {如果(!fragment.equals(currentFragment)){片段管理器.beginTransaction().replace(R.id.armen,片段,标签).犯罪();currentFragment = 片段;}}@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);fragmentManager = getSupportFragmentManager();片段片段 = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);如果(片段==空){fragment = FragmentFirst.newInstance();}替换片段(片段,TAG_FRAGMENT_ONE);BottomNavigationView 导航 = (BottomNavigationView) findViewById(R.id.navigation);navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);}}

解决方案

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

公共类 MainActivity 扩展 AppCompatActivity {boolean doubleBackToExitPressedOnce = false;final Fragment fragment1 = new HomeFragment();final Fragment fragment2 = new DashboardFragment();final Fragment fragment3 = new NotificationsFragment();最终 FragmentManager fm = getSupportFragmentManager();片段活动 = 片段 1;底部导航视图导航;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);工具栏工具栏 = (工具栏) findViewById(R.id.toolbar);setSupportActionBar(工具栏);导航 = (BottomNavigationView) findViewById(R.id.navigation);navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);setFragment(fragment1, 1", 0);}private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener= new BottomNavigationView.OnNavigationItemSelectedListener() {@覆盖public boolean onNavigationItemSelected(@NonNull MenuItem item) {开关(item.getItemId()){案例 R.id.navigation_home:setFragment(fragment1, 1", 0);返回真;案例 R.id.navigation_dashboard:setFragment(fragment2, 2", 1);返回真;案例 R.id.navigation_notifications:setFragment(fragment3, 3", 2);返回真;}返回假;}};public void setFragment(Fragment fragment, String tag, int position) {如果(片段.isAdded()){fm.beginTransaction().hide(active).show(fragment).commit();} 别的 {fm.beginTransaction().add(R.id.main_container, fragment, tag).commit();}navigation.getMenu().getItem(position).setChecked(true);活动 = 片段;}@覆盖公共布尔 onCreateOptionsMenu(菜单菜单){getMenuInflater().inflate(R.menu.main_menu, menu);返回 super.onCreateOptionsMenu(menu);}@覆盖公共布尔 onOptionsItemSelected(MenuItem item) {int id = item.getItemId();如果(id == R.id.action_settings){开始活动(新意图(MainActivity.this,SettingsActivity.class));返回真;}返回 super.onOptionsItemSelected(item);}@覆盖公共无效 onBackPressed() {如果(活动 == 片段 1){如果(doubleBackToExitPressedOnce){super.onBackPressed();返回;}this.doubleBackToExitPressedOnce = true;Toast.makeText(this, "请再次单击返回退出", Toast.LENGTH_SHORT).show();} 别的 {setFragment(fragment1, 1", 0);}}}

I would like to make a bottom navigation bar in my project. Every view has it's own fragment. The problem is that every time i click on the button to change the view for example from recents to favorites it creates new fragment with completely new states(e.g. scroll position, text changed whatever my fragment contains). I know that in official Android documentation there was written that bottom navigation bar should reset the task states, but i think it is too uncomfortable for users. I would like to have kind of similar functionality like instagram that you change from feed to explore and back to feed the scroll position the image caches everything remains saved. I tried almost every way to solve this problem the only thing that worked is by setting visibility GONE and setting visibility VISIBLE according to situation but i understand that it is not RIGHT way there should be better way of doing this and i am not talking about manually saving needed instances. I followed almost every tutorial about bottom nav fragments but the interesting thing is that no one is interested to make it use without calling new every time.

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;
    }
});

I also tried the onAttach and Deattach solutions but again no success.

VIDEO LINK : new i tried Nino Handler version it only works when i tap on the same fragment button

Maybe it is connected that i am using canary version or something wrong in my gradle dependencies?

NEW UPDATES:

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);
    }

}

解决方案

I had similar issue, but this code solved my problem.

public class MainActivity extends AppCompatActivity {

    boolean doubleBackToExitPressedOnce = false;
    final Fragment fragment1 = new HomeFragment();
    final Fragment fragment2 = new DashboardFragment();
    final Fragment fragment3 = new NotificationsFragment();
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active = fragment1;
    BottomNavigationView navigation;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        setFragment(fragment1, "1", 0);
    }


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

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    setFragment(fragment1, "1", 0);
                    return true;
                case R.id.navigation_dashboard:
                    setFragment(fragment2, "2", 1);
                    return true;
                case R.id.navigation_notifications:
                    setFragment(fragment3, "3", 2);
                    return true;
            }
            return false;
        }
    };

    public void setFragment(Fragment fragment, String tag, int position) {
        if (fragment.isAdded()) {
            fm.beginTransaction().hide(active).show(fragment).commit();
        } else {
            fm.beginTransaction().add(R.id.main_container, fragment, tag).commit();
        }
        navigation.getMenu().getItem(position).setChecked(true);
        active = fragment;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            startActivity(new Intent(MainActivity.this, SettingsActivity.class));
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if (active == fragment1) {
            if (doubleBackToExitPressedOnce) {
                super.onBackPressed();
                return;
            }
            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
        } else {
            setFragment(fragment1, "1", 0);
        }
    }
}

这篇关于BottomNavigationView - 如何避免重新创建 Fragment 并重用它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆