片段中的元素在 re-adding 相同片段后不起作用
Elements in Fragment not working after re-adding the same fragment
UPDATE:我发现 header 不是唯一受影响的东西,但 listeners
和片段中的其他元素没有受到影响初始化。 (例如 FAB)。唯一能正常运行的是 adapter
(即 ListView
行)
中内置的所有内容
问题:打开导航抽屉,单击一个列表项,在同一个 Activity
中打开一个新的 Fragment
。再次打开导航抽屉,单击应该简单地替换现有 Fragment
的相同项目,当 Fragment
打开时,所有在 Java 中以编程方式设置的元素(文本、颜色, listeners) 不是 changed/added 到 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
和一个 header.
Fragment
,(PlannerFragment
) 第一次加载正常。
当我单击另一个项目(不同的 PlanType
)时,它转到相同的 Fragment
(上面执行的相同代码):ListView
在实际列表中加载正常。 但是 在 header
列表中, none 的 setText()
值正确设置了新数据。它使用我的 xml
布局中的默认值。
现在,如果我在两者之间加载不同的 Fragment
,一切都会很好。只有当我在旧的上面添加或替换(我都试过)相同的 Fragment
时才会发生这种情况。
这是 PlannerFragment
顶部的 header 代码
@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();
这没有效果。
同样,这只发生在我更改上面的库时。这是库的错误还是它现在的响应不同?
appcompat 25.1.0 上的片段有许多 变化和问题。第一个似乎与您的问题有关,但应该阅读下两个,因为它可能很重要。
FragmentTransaction 替换行为
替换在 appCompat 25.1.0 中无法正常工作
当前状态(2017 年 1 月 4 日):bug 已分配
Issue link
25.1.0 上的片段生命周期更改
新片段的 onStart 在前一个片段的 onStop 之前被调用
当前状态:按预期工作。对我来说,这可能是 app compat 25 的重大变化。0.x
Issue link
在片段中 调用两次 的恢复事件也存在问题,请参阅 here。
TLDR. 也许最好的临时解决方案是在新版本发布之前不要使用 25.1.0。
您可以在 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");
}
}
UPDATE:我发现 header 不是唯一受影响的东西,但 listeners
和片段中的其他元素没有受到影响初始化。 (例如 FAB)。唯一能正常运行的是 adapter
(即 ListView
行)
中内置的所有内容
问题:打开导航抽屉,单击一个列表项,在同一个 Activity
中打开一个新的 Fragment
。再次打开导航抽屉,单击应该简单地替换现有 Fragment
的相同项目,当 Fragment
打开时,所有在 Java 中以编程方式设置的元素(文本、颜色, listeners) 不是 changed/added 到 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
和一个 header.
Fragment
,(PlannerFragment
) 第一次加载正常。
当我单击另一个项目(不同的 PlanType
)时,它转到相同的 Fragment
(上面执行的相同代码):ListView
在实际列表中加载正常。 但是 在 header
列表中, none 的 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();
这没有效果。
同样,这只发生在我更改上面的库时。这是库的错误还是它现在的响应不同?
appcompat 25.1.0 上的片段有许多 变化和问题。第一个似乎与您的问题有关,但应该阅读下两个,因为它可能很重要。
FragmentTransaction 替换行为
替换在 appCompat 25.1.0 中无法正常工作
当前状态(2017 年 1 月 4 日):bug 已分配
Issue link
25.1.0 上的片段生命周期更改
新片段的 onStart 在前一个片段的 onStop 之前被调用
当前状态:按预期工作。对我来说,这可能是 app compat 25 的重大变化。0.x
Issue link
在片段中 调用两次 的恢复事件也存在问题,请参阅 here。
TLDR. 也许最好的临时解决方案是在新版本发布之前不要使用 25.1.0。
您可以在 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");
}
}