Spinner onItemSelected 被错误调用(无需用户操作)
我有一个在对话框视图中显示的微调器,当对话框启动时 onItemSelected
被调用。我真的不想处理这个,但只有当用户做出选择时。所以我要么需要阻止这种情况(也许是因为没有设置默认值?),要么我需要知道不是用户在做出此选择?
I have a spinner which I am showing in a dialog view, and the moment the dialog starts onItemSelected
is called. I don't really want to process this but only when user makes the selection. So I either need to prevent this (maybe because no default value is set?), or I need to know it is not the user that is making this selection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
符合 Bill Mote 解决方案精神的另一个选择是使
OnItemSelectedListener
也成为OnTouchListener
。然后,可以在 onTouch 方法中将用户交互标志设置为 true,并在处理选择更改后在onItemSelected()
中重置。我更喜欢这个解决方案,因为用户交互标志是专门为微调器处理的,而不是为活动中可能影响所需行为的其他视图处理的。在代码中:
为微调器创建侦听器:
将侦听器作为
OnItemSelectedListener
和OnTouchListener
添加到微调器:Another option in the spirit of Bill Mote's solution is to make the
OnItemSelectedListener
also anOnTouchListener
. The user interaction flag can then be set to true in the onTouch method and reset inonItemSelected()
once the selection change has been handled. I prefer this solution because the user interaction flag is handled exclusively for the spinner, and not for other views in the activity that may affect the desired behavior.In code:
Create your listener for the spinner:
Add the listener to the spinner as both an
OnItemSelectedListener
and anOnTouchListener
:你可以简单地添加一个 int count 来解决它:)
You can simply add an int count to solve it :)
从 API 级别 3 开始,您可以在 Activity 上使用带有布尔值的 onUserInteraction() 来确定用户是否正在与设备交互。
http://developer.android.com/reference/android/app/Activity.html# onUserInteraction()
作为 Activity 上的一个字段,我有:
最后,我的微调器:
当您进入并浏览 Activity 时,布尔值将重置为 false。就像魅力一样。
Beginning with API level 3 you can use onUserInteraction() on an Activity with a boolean to determine if the user is interacting with the device.
http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()
As a field on the Activity I have:
Finally, my spinner:
As you come and go through the activity the boolean is reset to false. Works like a charm.
Androider,我找到了这个问题的解决方案并将其发布在这里(带有代码示例):
Spinner onItemSelected() 在不应该执行时执行
Androider, I have found a solution for this problem and posted it here (with code sample):
Spinner onItemSelected() executes when it is not suppose to
我用不同的方式解决了这个问题,因为我注意到有时 onItemSelected 方法在方向改变时被调用两次,有时甚至一次。
这似乎取决于当前微调器的选择。所以旗帜或计数器对我不起作用。相反,我使用 onResume() 和 onCreate 记录系统时间
widgetsRestartTime = System.currentTimeMillis()
widgetsRestartTime 被声明为 double 和实例变量。
现在,在 onItemSelected() 方法中,我再次检查当前时间并从中减去 widgetsRestartTime,如下所示:
if (System.currentTimeMillis() - widgetsRestartTime > 200) {
// 用户触发的事件 - 所以这是一个真正的旋转事件,所以处理它
} 别的 {
// 系统生成的事件,例如方向改变、活动启动。所以忽略
}
I have solved this problem a different way as I noticed sometimes the onItemSelected method was called twice on orientation change or sometimes once.
It seemed to depend on the current spinner selection. So a flag or counter didn't work for me. Instead I record the system time in BOTH onResume() and onCreate using
widgetsRestartTime = System.currentTimeMillis()
widgetsRestartTime is declared as a double and as an intance variable.
Now in the onItemSelected() method I check the current time again and subtract widgetsRestartTime from it as follows:
if (System.currentTimeMillis() - widgetsRestartTime > 200) {
// user triggered event - so this is a real spinner event so process it
} else {
// system generated event e.g. orientation change, activity startup. so ignore
}
我遇到了同样的问题,我通过记住之前选择的微调值来解决它。在每次 onItemSelected 调用中,我都会将新值与前一个值进行比较,如果相同,我不会进一步处理代码。
I had the same problem, and I solved it by remembering the previous selected spinner value. On each onItemSelected call I compare the new value with the previous, and if it's the same I don't process the code further.
我也有同样的问题。但接受的解决方案对我来说不起作用,因为我的表单上有多个旋转器,其中一些是隐藏的,当旋转器隐藏时,监听器不会触发,所以计数对我来说不是一个解决方案。
不过,我找到了另一个解决方案:
就是这样,它就像一个魅力!
侦听器中的示例:
PS 这适用于设置为多个微调器的同一个侦听器!
I had the same problem. But the accepted solution didn't work for me because I have multiple spinners on my form, and some of them are hidden, and when the spinners are hidden, the listener does not fire, so counting is not a solution for me.
I have found another solution though:
That's it, it works like a charm!
Example in the listener:
P.S. And this works for the same listener set to multiple spinners!
是的,您所看到的是正确的,并且是默认行为,您无法阻止这种情况。 OnItemSelected 回调在初始加载时调用。初始加载后,仅当用户更改选择或您在代码中更改选择时才会触发。您可以有一个指示器,它可以告诉您该事件是否是初始加载的结果,如果您不想处理它,则可以忽略第一个事件。
Yes what you are seeing is correct and is the default behaviour,You cannot prevent this. The OnItemSelected callback is called on initial load. After that initial load it is only triggered whenever user changes selection or if you change the selection from within your code. You can have a indicator which can tell you whether the event was a result of initial load and ignore the first event if you do not want to process it.
如果您还购买 最初未选择的微调器,您可以选择
因为项目 0 永远不可能被选择。干杯:-)
If you also are shopping for an initially unselected Spinner, you can go with
Since item 0 is never possible to select. Cheers :-)
它对我有用,
private boolean isSpinnerInitial = true;
It worked for me,
private boolean isSpinnerInitial = true;
我也在互联网上寻找好的解决方案,但没有找到满足我需求的解决方案。
因此,我在 Spinner 类上编写了此扩展,以便您可以设置一个简单的 OnItemClickListener,它具有与 ListView 相同的行为。
仅当“选择”某个项目时,才会调用 onItemClickListener。
玩得开心!
I also looked for a good solution on the internet but didn't find any that satisfied my needs.
So I've written this extension on the Spinner class so you can set a simple OnItemClickListener, which has the same behaviour as a ListView.
Only when an item gets 'selected', the onItemClickListener is called.
Have fun with it!
你应该这样做。顺序是关键。
You should do like this.The sequence is the key.
您可以尝试使用两个参数设置微调器,如下所示:
因此,将其放在设置 OnItemSelectedListener 之前:
您可以从开发人员页面查看更多信息:
https://developer.android.com/reference/android/widget/Spinner.html
You can try to set the spinner using two arguments, like this:
So, put this before the set OnItemSelectedListener :
You can check more from the developers page:
https://developer.android.com/reference/android/widget/Spinner.html
如果您不介意使用提示位置,则每次您想要在旋转器上做工作人员时都可以执行类似的操作。首先将选择设置为提示:
然后在选择发生时执行类似的操作:
If you dont mind using a position for promt you can do something like this every time you want to do staff on the spinner. First set selection to the promt:
And then do something like that when selection happens:
问题是我们在微调器完成渲染之前设置侦听器。一旦渲染,它就会自动选择数据集的第一个选项(这很好),但这会导致我们的侦听器触发。
解决方案是等待特定的微调器被布局,然后才设置监听器:
The issue is that we are setting listener before the spinner has done rendering. And once it renders, it does select it's datasets 1st option automatically (which is fine), but that causes our listener to trigger.
The solution is to wait for the specific spinner to be laid out, and only then set the listener:
这是 Andres Q 答案的 Kotlin 版本,并进行了一些改进。
匿名接口实现:
然后,将微调器的侦听器设置为 OnItemSelectedListener 和 OnTouchListener:
This is the Kotlin version of Andres Q's answer with some improvements.
Anonymous interface implementation:
Then, Set the listener to the spinner as both an OnItemSelectedListener and an OnTouchListener: