重新添加相同的片段后片段中的元素不起作用

Posted

技术标签:

【中文标题】重新添加相同的片段后片段中的元素不起作用【英文标题】:Elements in Fragment not working after re-adding the same fragment 【发布时间】:2017-05-15 04:32:53 【问题描述】:

更新:我发现标题不是唯一受影响的东西,但listeners 和片段中的其他元素没有被初始化。 (如 FAB 的)。唯一能正常工作的是在 adapter 内构建的任何东西(即 ListView 行)

问题:打开导航抽屉,单击列表项,在同一Activity 中打开一个新Fragment。再次打开导航抽屉,单击应该简单地替换现有Fragment 的相同项目,当Fragment 确实打开时,所有在 Java 中以编程方式设置的元素(文本、颜色、侦听器)都不会更改/添加到Fragment。该视图只是默认的xml 布局。我已通过Log.d 确认设置这些东西的代码正在运行。 (如果你打开一个不同的Fragment 然后回到原来的那个,一切正常)

已确认的原因:更改时:

    compile "com.android.support:appcompat-v7:25.0.1"
    compile 'com.android.support:design:25.0.1'

    compile "com.android.support:appcompat-v7:25.1.0"
    compile 'com.android.support:design:25.1.0'

(如果只更改了这些库中的一个,不管是哪个,问题仍然存在)

我已确认更改这两个库是问题所在(也在第二个应用程序中确认了此问题——并且更改此代码,结果完全相同)

我的问题是,为什么会发生这种情况以及如何解决?

原始问题的代码和更详细的描述:

                FragmentTransaction tItems = fm.beginTransaction();
                ListFragment mFrag = new PlannerFragment();
                tItems.replace(R.id.main_frag, mFrag, TAG_CALC_FRAGMENT);
                tItems.commit();

我的抽屉里大约有 4 个选项都打开了这个 Fragment,但在每个选项之前,我都设置了一个全局变量,如下所示:

MyApp.PlanType = "highbal";
MyApp.PlanType = "lowbal";
etc.

基于PlanType 值(上图),Fragment 加载了不同的数据(但是,在完全相同的 xml 布局中)。它只是一个带有标题的ListView

Fragment, (PlannerFragment) 第一次加载正常。

当我点击另一个项目(不同的PlanType)时,它转到相同的Fragment(上面执行的代码相同):ListView 在实际列表中加载良好。 但是在列表中的header 中,没有一个setText() 值正确设置了新数据。它使用我的 xml 布局中的默认值。

现在,如果我在两者之间加载不同的Fragment,一切都会很好。只有当我在旧的顶部添加或替换(我都尝试过)相同的Fragment 时才会发生这种情况。

这是PlannerFragment顶部的标头代码

@Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);

        // Setup listview
        lv = getListView();

        LayoutInflater inflaterHeader = getActivity().getLayoutInflater();
        ViewGroup header = (ViewGroup) inflaterHeader.inflate(R.layout.planner_listview_header, lv, false);
        lv.addHeaderView(header, null, false);

        // Load Data then Set Textviews, e.g.:
        TextView title = (TextView) getActivity().findViewById(R.id.tvPlannerTitle);
    dateOutput = (TextView) getActivity().findViewById(R.id.tvDebtOutDate);

如果我添加到该代码,dateOutput.setText("test"); 它不会发生。我可以做一个Log.d和我的数据寄存器,所以这段代码正在被读取,但 UI 没有设置。

我什至尝试过像这样先用支票删除Fragment

                Fragment fragment = fm.findFragmentByTag(TAG_CALC_FRAGMENT);
                if(fragment != null)
                    fm.beginTransaction().remove(fragment).commit();

这没有效果。

同样,这仅在我更改上述库时发生。这是库的错误还是它现在的响应不同?

【问题讨论】:

尝试在tItems.commit();之后调用ft.executePendingTransactions() @OlegBogdanov 我在你说的那一行之后做了一个fm.executePendingTransactions();,我得到了同样的结果。 请更新您的问题并将您的片段的onCreateView 【参考方案1】:

appcompat 25.1.0 上的片段有许多变化和问题。第一个似乎与您的问题有关,但应该阅读下两个,因为它可能很重要。


FragmentTransaction 替换行为

替换在 appCompat 25.1.0 中无法正常工作当前状态(2017 年 1 月 4 日):错误 已分配@ 987654321@


25.1.0 上的片段生命周期变化

新片段的 onStart 在前一个片段的 onStop 之前调用当前状态:按预期工作。对我来说,这可能是 app compat 25.0.x 的重大变化 Issue link

片段中的 resume 事件被调用两次也存在问题,请参阅here。

TLDR。也许最好的临时解决方案是在新版本发布之前不要使用 25.1.0。

【讨论】:

我有一种强烈的感觉,这是库中的一个错误。感谢您确认。 在最近几次支持库升级中,与上述严重程度相似的错误数量令人非常失望;感谢@Hugo的链接【参考方案2】:

您可以在navigationDrawer() 方法中添加list_view_header.xml 并更改所选项目的位置,例如selectItem(position - 1)

  private void navigationDrawer() 

        mTitle = mDrawerTitle = getTitle();
        // mNavigationDrawerItemTitles = getResources().getStringArray(R.array.navigation_drawer_items_array);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        LayoutInflater inflater = getLayoutInflater();
        View listHeaderView = inflater.inflate(R.layout.list_view_header, null, false);
        mDrawerList.addHeaderView(listHeaderView, null, false);

        setupToolbar();

        DataModel[] drawerItem = new DataModel[6];

        drawerItem[0] = new DataModel(R.drawable.dashboard_icon, "Dashboard");
        drawerItem[1] = new DataModel(R.drawable.cal_icon, "Calender");
        drawerItem[2] = new DataModel(R.drawable.classes, "Classes");
        drawerItem[3] = new DataModel(R.drawable.message_icon_hdpi, "Message Center");
        drawerItem[4] = new DataModel(R.drawable.profile, "Profile & Setting");
        drawerItem[5] = new DataModel(R.drawable.bulletin_icon, "Bulletin Board");

        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        getSupportActionBar().setHomeButtonEnabled(true);

        DrawerItemCustomAdapter adapter = new DrawerItemCustomAdapter(this, R.layout.list_view_item_row, drawerItem);
        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        setupDrawerToggle();


    

    private class DrawerItemClickListener implements ListView.OnItemClickListener 

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            selectItem(position - 1);
        


    

    private void selectItem(int i) 
        Fragment fragment = null;

        switch (i) 
            case 0:
                fragment = new Fragment_DashBoard();
                // toolbar.setTitle("Dashboard");
                Titletv.setText("Dashboard");
                break;
            case 1:
                fragment = new Fragment_Calender();
                // toolbar.setTitle("Calender");
                Titletv.setText("Calender");

                break;
            case 2:
                fragment = new Fragment_Classes();
                // toolbar.setTitle("Classes");
                Titletv.setText("Classes");
                break;
            case 3:
                fragment = new Fragment_MessageCenter();
                // toolbar.setTitle("Message");
                Titletv.setText("Messages");
                break;
            case 4:
                fragment = new Fragment_ProfileSetting();
                // toolbar.setTitle("Profile");
                Titletv.setText("Profile");

                break;

            case 5:
                fragment = new Fragment_BulletinBoard();
                //toolbar.setTitle("Bulletin Board");
                Titletv.setText("Bulletin Board");

                break;

            default:
                break;
        


        if (fragment != null) 

            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction trans = fragmentManager.beginTransaction();
            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null).commit();

            mDrawerList.setItemChecked(i, true);
            mDrawerList.getItemAtPosition(i);
            // setTitle(mNavigationDrawerItemTitles[position]);
            mDrawerLayout.closeDrawer(mDrawerList);


         else 
            Log.e("MainActivity", "Error in creating fragment");
        


    

【讨论】:

以上是关于重新添加相同的片段后片段中的元素不起作用的主要内容,如果未能解决你的问题,请参考以下文章

片段中的 Android ListView ArrayAdapter 不起作用

共享元素转换在父片段和子片段之间不起作用(嵌套片段)

共享元素片段转换不起作用

导航 PopUpToInclusive 不起作用?重新打开应用程序时,它会打开登录片段而不是电子邮件登录片段

添加到片段时按钮不起作用

片段中的按钮在android中不起作用