我有一个在对话框视图中显示的微调器,并且在对话框开始的那一刻onItemSelected
被调用。我真的不想处理这个,但只有当用户做出选择时。所以我要么需要阻止这种情况(可能是因为没有设置默认值?),要么我需要知道不是用户做出了这个选择?
15 回答
根据 Bill Mote 解决方案的精神,另一种选择是OnItemSelectedListener
将OnTouchListener
. 然后可以在 onTouch 方法中将用户交互标志设置为 true,并在onItemSelected()
处理了选择更改后重置。我更喜欢这个解决方案,因为用户交互标志是专门为微调器处理的,而不是为活动中可能影响所需行为的其他视图处理。
在代码中:
为微调器创建侦听器:
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;
}
}
}
将侦听器作为 anOnItemSelectedListener
和 an添加到微调器OnTouchListener
:
SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
您可以简单地添加一个 int 计数来解决它:)
sp.setOnItemSelectedListener(new OnItemSelectedListener() {
int count=0;
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if(count >= 1){
int item = sp.getSelectedItemPosition();
Toast.makeText(getBaseContext(),
"You have selected the book: " + androidBooks[item],
Toast.LENGTH_SHORT).show();
}
count++;
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
从 API 级别 3 开始,您可以在带有布尔值的 Activity 上使用 onUserInteraction() 来确定用户是否正在与设备交互。
http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()
@Override
public void onUserInteraction() {
super.onUserInteraction();
userIsInteracting = true;
}
作为 Activity 的一个字段,我有:
private boolean userIsInteracting;
最后,我的微调器:
mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
spinnerAdapter.setmPreviousSelectedIndex(position);
if (userIsInteracting) {
updateGUI();
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
当您来回进行活动时,布尔值将重置为 false。奇迹般有效。
Androider,我找到了解决此问题的方法并将其发布在此处(带有代码示例):
我已经以不同的方式解决了这个问题,因为我注意到有时 onItemSelected 方法在方向更改时被调用两次,有时被调用一次。
它似乎取决于当前的微调器选择。所以标志或计数器对我不起作用。相反,我使用 widgetsRestartTime = System.currentTimeMillis() 在 onResume() 和 onCreate 中记录系统时间
widgetsRestartTime 被声明为双精度变量和实例变量。
现在在 onItemSelected() 方法中,我再次检查当前时间并从中减去 widgetsRestartTime,如下所示: if (System.currentTimeMillis() - widgetsRestartTime > 200) { // 用户触发事件 - 所以这是一个真正的微调器事件,所以处理它} else { // 系统生成的事件,例如方向改变,活动启动。所以忽略}
我有同样的问题,我通过记住之前选择的微调器值来解决它。在每次 onItemSelected 调用中,我都会将新值与前一个值进行比较,如果相同,则不再进一步处理代码。
我有同样的问题。但是接受的解决方案对我不起作用,因为我的表单上有多个微调器,其中一些是隐藏的,当微调器隐藏时,侦听器不会触发,所以计数不是我的解决方案。
我找到了另一种解决方案:
- 在初始化微调器时,在活动的 onCreate() 或 Fragment 的 onCreateView 中以及在设置侦听器之前,在微调器上设置默认 TAG
- 在监听器中,检查标签,如果它存在,然后删除它并且不执行代码,通过返回。
就是这样,它就像一个魅力!
监听器中的示例:
if(((String)parent.getTag()).equalsIgnoreCase(TAG_SPINNERVALUE))
{
parent.setTag("");
return;
}
PS 这适用于设置为多个微调器的同一个侦听器!
它对我有用,
private boolean isSpinnerInitial = true;
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
if(isSpinnerInitial)
{
isSpinnerInitial = false;
}
else {
// do your work...
}
}
如果您还在购买最初未选择的 Spinner,您可以选择
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if(pos != 0) {
pos--;
// your code here
}
}
由于项目 0 永远无法选择。干杯:-)
是的,您所看到的是正确的,并且是默认行为,您无法阻止这种情况。OnItemSelected 回调在初始加载时调用。在初始加载之后,仅当用户更改选择或您从代码中更改选择时才会触发它。您可以有一个指示器,它可以告诉您该事件是否是初始加载的结果,如果您不想处理它,则忽略第一个事件。
我还在互联网上寻找了一个好的解决方案,但没有找到任何满足我需求的解决方案。所以我在 Spinner 类上编写了这个扩展,这样你就可以设置一个简单的 OnItemClickListener,它的行为与 ListView 相同。
只有当一个项目被“选中”时,才会调用 onItemClickListener。
玩得开心!
public class MySpinner extends Spinner
{
private OnItemClickListener onItemClickListener;
public MySpinner(Context context)
{
super(context);
}
public MySpinner(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public MySpinner(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener inOnItemClickListener)
{
this.onItemClickListener = inOnItemClickListener;
}
@Override
public void onClick(DialogInterface dialog, int which)
{
super.onClick(dialog, which);
if (this.onItemClickListener != null)
{
this.onItemClickListener.onItemClick(this, this.getSelectedView(), which, this.getSelectedItemId());
}
}
}
你应该这样做。顺序是关键。
spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
您可以尝试使用两个参数设置微调器,如下所示:
spinner.setSelection(count, false);
所以,把它放在集合 OnItemSelectedListener 之前:
spinner.setSelection(0,false);
您可以从开发人员页面查看更多信息:
https://developer.android.com/reference/android/widget/Spinner.html
问题是我们在微调器完成渲染之前设置了监听器。一旦渲染,它会自动选择它的 datasets 1st 选项(这很好),但这会导致我们的监听器触发。
解决方案是等待特定的微调器被布局,然后才设置监听器:
binding.spinnerLanguage.post( new Runnable() {
@Override
public void run() {
binding.spinnerLanguage.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
GeneralUtils.log(TAG, "finally, not triggering on initial render");
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
});
如果您不介意使用提示职位,则每次您想在微调器上做员工时都可以这样做。首先将选择设置为提示:
spinner.setselected(0);
spinner.add("something");
...
然后在选择发生时执行类似的操作:
spinner.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) =>
{
if (spinner.SelectedItemPosition != 0)
{
//do staff
}
}