Android Can';旋转屏幕后找不到旋转器
我使用“Fragment”获得一个包含两个“Fragment”的布局,因此我的类扩展了“Fragment” 我在左边的“片段”上加载一个“列表视图”,在右边的“片段”上加载另一个修改过的“列表视图”。在这里,我有一个“旋转器”,我必须改变它的颜色 我有以下代码:Android Can';旋转屏幕后找不到旋转器,android,android-layout,listview,android-fragments,Android,Android Layout,Listview,Android Fragments,我使用“Fragment”获得一个包含两个“Fragment”的布局,因此我的类扩展了“Fragment” 我在左边的“片段”上加载一个“列表视图”,在右边的“片段”上加载另一个修改过的“列表视图”。在这里,我有一个“旋转器”,我必须改变它的颜色 我有以下代码: private void loadSpinner(int value) { //Not relevant code adapter = new ArrayAdapter<CharSequence>(getA
private void loadSpinner(int value) {
//Not relevant code
adapter = new ArrayAdapter<CharSequence>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_item, data);
adapter.setDropDownViewResource(R.layout.spinner);
spinner.setAdapter(adapter);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String value = parent.getItemAtPosition(position).toString();
((TextView) parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black));
//Some code
}
private void loadSpinner(int值){
//非相关代码
adapter=new ArrayAdapter(getActivity().getApplicationContext(),android.R.layout.simple\u微调器\u项,数据);
adapter.setDropDownViewResource(R.layout.spinner);
旋转器。设置适配器(适配器);
}
@凌驾
已选择公共视图(AdapterView父视图、视图视图、整型位置、长id){
字符串值=parent.getItemAtPosition(position).toString();
((TextView)parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black));
//一些代码
}
在我旋转设备屏幕之前,上面的代码按预期工作。在这里,我在((TextView)parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black))得到一个nullpointerexception
代码>
如果我对上述行进行注释,因为我在旋转屏幕之前保存状态,所以在旋转屏幕之后,我的数据将恢复,并且所有工作都按预期进行,除了处于浅色的微调器,因此可见性差
我知道我可以创建自己的“微调器”布局并解决此问题,但我想知道如何解决此问题。屏幕旋转后,您的微调器视图尚未附加任何子视图(您可以通过调用parent.getChildCount()
进行验证),因此您的parent.getChildAt(0)
返回空值,导致NPE
解释
创建活动后,Android通过为布局层次结构中的每个视图调用onMeasure()
,然后调用onLayout()
来显示其内容。
Spinner
将在调用onLayout()
的过程中创建其子视图,并使用适配器中的数据填充这些子视图,尽可能附加这些子视图。
因此,通常情况下,对于微调器,您将有序列:onMeasure
->onLayout
->onimselected
而且,由于在选择onlineout
之前调用了onlineout
,所以在初始活动启动期间,一切都很好
现在,让我们看看旋转屏幕时会发生什么:
在销毁活动之前,将调用它的onSavedInstanceState
,它将调用传播到微调器的onSavedInstanceState
,该微调器将保存当前选定的位置
旋转后,将重新创建活动,然后调用其onRestoreInstanceState
。
当调用Activity#onRestoreInstanceState
时,它最终将调用Spinner's,其代码如下:
SavedState ss = (SavedState) state;
//...some code
if (ss.selectedId >= 0) {
mDataChanged = true;
//...some more code
}
如您所见,若微调器的上一个状态是使用保存的,它将始终设置mDataChanged标志
然后调用,它具有以下代码段:
if (mDataChanged) {
handleDataChanged();
}
()的实现最终将调用(),触发Spinner的onItemSelected
因此在onMeasure
期间,在onLayout
之前调用onimselected
。
如上所述,Spinner
在调用其onLayout
之前没有子项
希望问题现在清楚了
变通办法
要确认该行为并解决NPE,您只需在活动中为onSavedInstanceState
/onRestoreInstanceState
提供空实现即可(无需调用超级实现):
这将阻止设置mDataChanged
,并且onMeasure
不会触发fireOnSelected
附加说明
不调用“活动”super。
在覆盖SavedInstanceState
/onRestoreInstanceState
时,绝对不建议执行,因为至少您将无法自动保存内部视图(包括微调器)的状态。
我鼓励您这样做只是为了验证上面解释的行为,并查看NPE
是否消失
更好的解决方案是在.xml布局中为微调器项定义所需颜色的TextView
,并使用它为微调器构建ArrayAdapter
。从何处调用loadSpinner
?@Szymon Hi。在onCreateView
我正在做这个spinner=(spinner)itemDataLayout.findviewbyd(R.id.availableValues);spinner.setOnItemSelectedListener(此)代码>和微调器从,想象一下,functionX
加载。当我单击左侧列表视图
上的项目时,调用函数functionX
。如果我来自一个savedrestoredstate
,则会从onStart()
调用functionX
,您可能在调用loadSpinner
之前触发了onItemSelected
,这将设置适配器。您可以通过将断点放在选中的onimselected
和第行spinner.setAdapter()
中来验证顺序,并查看在rotation@Favolas如果我在前面的评论中所写的是这种情况,那么您将始终在onItemSelected
中选择NPE,因为spinner尚未显示任何子项。所以,你有两个选择来解决这个问题,但首先你需要检查情况是否如此。@kiruwka-NoploadSpinner
是第一位的,非常感谢您的解释。你是对的。“要实现我的自定义微调器了。”法沃拉斯很高兴它起了作用。请考虑接受。新年快乐!嘿..我遇到了同样的问题..我实现了我的自定义微调器..仍然得到相同的nullpointerexception
。您是否使用自定义微调器或其他方法解决了此问题?我在@Favolas解决了它,您的
@Override
protected void onSaveInstanceState(Bundle outState) { /* do nothing */ }