来自背景后出现的其他片段之上的片段

时间:2019-04-22 11:53:56

标签: android android-fragments

我正在使用以下代码,该代码利用底部导航并显示3个不同的片段。该代码运行完美。但是问题是有时应用程序在后台停留的时间过长,并且用户返回到屏幕时,第一个片段显示得很好,但是在单击第二个和第三个选项卡时,视图会失真,即,第一个和第二个的内容或第一和第三片段重叠。

public class HomeActivity extends AppCompatActivity {

private final Fragment fragment1 = new Fragment1();
private final Fragment fragment2 = new Fragment2();
private final Fragment fragment3 = new Fragment3();
private final FragmentManager fm = getSupportFragmentManager();

private Fragment active = fragment1;

private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = 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;
        };


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

    //Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));

    BottomNavigationView navigation = findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    fm.beginTransaction().add(R.id.container, fragment3, "3").hide(fragment3).commit();
    fm.beginTransaction().add(R.id.container, fragment2, "2").hide(fragment2).commit();
    fm.beginTransaction().add(R.id.container, fragment1, "1").commit();

}

}

该如何解决?任何帮助

3 个答案:

答案 0 :(得分:0)

在单击底部导航后,您只能在onCreate时添加一个片段,仅替换一个片段,并且在XML文件中不添加任何片段类。

private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = item -> {
                switch (item.getItemId()) {
                    case R.id.navigation_home:
                       setFragment(new fragment1());

                        return true;
                    case R.id.navigation_dashboard:
                        setFragment(new fragment2());

                        return true;
                    case R.id.navigation_notifications:
                       setFragment(new fragment3());

                        return true;
                }
                return false;
            };


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


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

  FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = 
                    fragmentManager.beginTransaction();
                fragmentTransaction.add(android.R.id.content, fragment1);
                fragmentTransaction.commit();


    }

    protected void setFragment(Fragment fragment) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = 
                    fragmentManager.beginTransaction();
                fragmentTransaction.replace(android.R.id.content, fragment);
                fragmentTransaction.commit();


       }

答案 1 :(得分:0)

尝试这种方式

为片段交易创建视图

<FrameLayout
   .....
    android:layout_above="@+id/navigation"
   ....
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 <android.support.design.widget.BottomNavigationView/>

,然后在您的课程中用片段替换框架布局 使用

 private boolean loadFragment(Fragment fragment) {
    if(fragment!=null ) {
        getSupportFragmentManager().beginTransaction()
        .addToBackStack(null)
        .replace(R.id.frame_container, fragment)
        .commit();
        return true;
    }
    return false;

}

答案 2 :(得分:0)

此答案的第二项最有可能是产生您描述的视觉效果(一个片段在另一个片段之上),但第1点和第3点也是您应考虑的重要方面。

1)保留Fragment实例。

由于实例可以被销毁和重新创建,因此无需保留片段实例(var cb0 = function (req, res, next) { console.log('CB0'); next(); } fragment1fragment1),只需保留对片段标签字符串的引用即可。 您现在所拥有的方式,屏幕上的片段可能与您在活动中实际上应该已经被垃圾收集的片段不同。 (内存泄漏)

当您需要对片段进行处理时,请使用fragment3

2)在活动的onCreate中创建fragmet

仅在SupportFragmentManager.findFragmentByTag(theGragmentTag);为空时在活动的onCreate(savedBundle)中创建fragments。否则,片段将开始复制,并且很可能在另一个之上显示您描述的行为。

3)碎片可以在背景中被破坏

假设该片段可能不在屏幕上时被破坏,因此请保存并恢复所需的信息。保存在savedBundle中,然后根据需要进行恢复:onPause()onResume()

注意:如果在片段可见时应该刷新UI,则仅setUserVisibleHint(boolean)不会执行此工作,因为在其邻居片段可见时可能已经调用了它。在这种情况下,您需要将onResume()onResume()结合使用,以便协调何时刷新UI。