我有一个带有三个微调器的布局。它们在下拉列表中显示的选项不同。
在我的onCreateView
我有一个设置微调器的方法。在这个方法里面我有这样的东西:
mySpinner = (Spinner) view.findViewById(R.id.my_spinner);
ArrayAdapter<String> mySpinner =
new ArrayAdapter<String>(getActivity(), R.layout.background,
new ArrayList<String>(Arrays.asList(getResources().getStringArray(R.array.spinner_one_data))));
mySpinner.setDropDownViewResource(R.layout.spinner_text);
mySpinner.setAdapter(mySpinner);
mySpinner.setOnItemSelectedListener(this);
正如我所说,我的另外两个旋转器几乎相同,但有不同的选择。
我知道在{first setup'中为每个微调器调用onItemSelected
一次,所以我有一个标志来防止这个问题。有了这个标志解决方案,我的微调器正在按预期工作。
问题是我在每个微调器中选择一个选项然后旋转屏幕。现在,onItemSelected
被调用6次而不是我期待的3次(我设置了一个标志来管理3次调用的这种情况)。
为什么会发生这种情况?我应该怎样处理这个问题?
答案 0 :(得分:28)
一般来说,我发现有许多不同的事件可以触发onItemSelected方法,很难跟踪所有这些事件。相反,我发现使用OnTouchListener仅响应用户启动的更改更简单。
为微调器创建监听器:
public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
boolean userSelect = false;
@Override
public boolean onTouch(View v, MotionEvent event) {
userSelect = true;
return false;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect) {
// Your selection handling code here
userSelect = false;
}
}
}
将侦听器作为OnItemSelectedListener和OnTouchListener添加到微调器:
SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
答案 1 :(得分:1)
我找到了一个适合我的解决方案。
我有3
个微调器,因此onItemSelected
在初始微调器设置时调用3
次。为避免onItemSelected
在初始设置中触发方法,我创建了一个计数器,因此onItemSelected
仅根据计数器值触发该方法。
我已经意识到,在我的情况下,如果旋转屏幕,onItemSelected
会再次触发3
次,加上每个微调器不在0
位置的时间1}}。
一个例子:
我有3
个微调器,用户将2
更改为其中一个可用选项,然后位置0
,这样他最终得到的情况如下:
First spinner - > Item 2 selected
Second spinner -> Item 0 selected (no changes)
Third spinner -> Item 1 selected
现在,如果我旋转屏幕,onItemSelected
将针对初始微调器设置加3
次,加上2
次,对于位置0
的微调器1}}。
@Override
public void onSaveInstanceState(Bundle outState) {
int changedSpinners = 0;
if (spinner1.getSelectedItemPosition() != 0) {
changedSpinners += 1;
}
if (spinner2.getSelectedItemPosition() != 0) {
changedSpinners += 1;
}
if (spinner3.getSelectedItemPosition() != 0) {
changedSpinners += 1;
}
outState.putInt("changedSpinners", changedSpinners);
}
我已将状态保存在onSaveInstanceState
中,然后在onCreateView
我检查了savedInstanceState != null
是否如此,如果是,则从捆绑中提取changedSpinners
并更新我的反对采取相应行动。
答案 2 :(得分:0)
扩展Andres Q.的答案...如果您使用的是Java 8,则可以通过使用lambda表达式来使用更少的代码行来实现。此方法还放弃了创建单独的类以实现onTouchListener
的需要。Boolean spinnerTouched; //declare this as an instance or class variable
spinnerTouched = false;
yourSpinner.setOnTouchListener((v,me) -> {spinnerTouched = true; v.performClick(); return false;});
yourSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(spinnerTouched){
//do your stuff here
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
//nothing selected
}
});
答案 3 :(得分:0)
仅仅检查片段是否处于恢复状态怎么样?有这样的想法:
private AdapterView.OnItemSelectedListener mFilterListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (isResumed()) {
//your code
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
//set mFilterListener
}
它消除了旋转问题和第一个设置问题。没有标志等。我在使用 TextWatchers 时遇到了同样的问题,并在评论中发现了这个 answer,这激发了我对这个解决方案的灵感。