27

我有一个在对话框视图中显示的微调器,并且在对话框开始的那一刻onItemSelected被调用。我真的不想处理这个,但只有当用户做出选择时。所以我要么需要阻止这种情况(可能是因为没有设置默认值?),要么我需要知道不是用户做出了这个选择?

4

15 回答 15

43

根据 Bill Mote 解决方案的精神,另一种选择是OnItemSelectedListenerOnTouchListener. 然后可以在 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);
于 2015-02-11T23:26:07.910 回答
23

您可以简单地添加一个 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) {
    }
});
于 2012-04-11T08:23:42.230 回答
11

从 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。奇迹般有效。

于 2014-07-31T23:39:39.420 回答
6

Androider,我找到了解决此问题的方法并将其发布在此处(带有代码示例):

Spinner onItemSelected() 在不应该执行时执行

于 2011-05-07T00:07:41.730 回答
4

我已经以不同的方式解决了这个问题,因为我注意到有时 onItemSelected 方法在方向更改时被调用两次,有时被调用一次。

它似乎取决于当前的微调器选择。所以标志或计数器对我不起作用。相反,我使用 widgetsRestartTime = System.currentTimeMillis() 在 onResume() 和 onCreate 中记录系统时间

widgetsRestartTime 被声明为双精度变量和实例变量。

现在在 onItemSelected() 方法中,我再次检查当前时间并从中减去 widgetsRestartTime,如下所示: if (System.currentTimeMillis() - widgetsRestartTime > 200) { // 用户触发事件 - 所以这是一个真正的微调器事件,所以处理它} else { // 系统生成的事件,例如方向改变,活动启动。所以忽略}

于 2011-10-27T20:39:59.163 回答
3

我有同样的问题,我通过记住之前选择的微调器值来解决它。在每次 onItemSelected 调用中,我都会将新值与前一个值进行比较,如果相同,则不再进一步处理代码。

于 2012-05-18T14:19:02.160 回答
3

我有同样的问题。但是接受的解决方案对我不起作用,因为我的表单上有多个微调器,其中一些是隐藏的,当微调器隐藏时,侦听器不会触发,所以计数不是我的解决方案。

我找到了另一种解决方案

  1. 在初始化微调器时,在活动的 onCreate() 或 Fragment 的 onCreateView 中以及在设置侦听器之前,在微调器上设置默认 TAG
  2. 在监听器中,检查标签,如果它存在,然后删除它并且不执行代码,通过返回。

就是这样,它就像一个魅力!

监听器中的示例:

        if(((String)parent.getTag()).equalsIgnoreCase(TAG_SPINNERVALUE))
        {
            parent.setTag("");
            return;
        }

PS 这适用于设置为多个微调器的同一个侦听器!

于 2012-07-02T09:23:46.033 回答
2

它对我有用,

private boolean isSpinnerInitial = true;

@Override
public void onItemSelected(AdapterView<?> parent, View view,
        int position, long id) {

    if(isSpinnerInitial)
    {
        isSpinnerInitial = false;
    }
    else  {
        // do your work...
    }

}
于 2015-01-21T08:42:07.907 回答
2

如果您还在购买最初未选择的 Spinner,您可以选择

@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    if(pos != 0) {
        pos--;

        // your code here
    }
}

由于项目 0 永远无法选择。干杯:-)

于 2013-06-23T16:10:31.020 回答
2

是的,您所看到的是正确的,并且是默认行为,您无法阻止这种情况。OnItemSelected 回调在初始加载时调用。在初始加载之后,仅当用户更改选择或您从代码中更改选择时才会触发它。您可以有一个指示器,它可以告诉您该事件是否是初始加载的结果,如果您不想处理它,则忽略第一个事件。

于 2011-02-26T17:35:49.567 回答
1

我还在互联网上寻找了一个好的解决方案,但没有找到任何满足我需求的解决方案。所以我在 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());
        }
    }
}
于 2012-01-03T15:20:34.080 回答
1

你应该这样做。顺序是关键。

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
于 2015-03-14T01:42:05.743 回答
1

您可以尝试使用两个参数设置微调器,如下所示:

spinner.setSelection(count, false);

所以,把它放在集合 OnItemSelectedListener 之前:

spinner.setSelection(0,false);

您可以从开发人员页面查看更多信息:

https://developer.android.com/reference/android/widget/Spinner.html

于 2018-03-13T14:45:22.273 回答
0

问题是我们在微调器完成渲染之前设置了监听器。一旦渲染,它会自动选择它的 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) {

            }
        });
    }
});
于 2021-07-09T08:47:22.843 回答
0

如果您不介意使用提示职位,则每次您想在微调器上做员工时都可以这样做。首先将选择设置为提示:

spinner.setselected(0);
spinner.add("something");
...

然后在选择发生时执行类似的操作:

spinner.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) => 
            {
                if (spinner.SelectedItemPosition != 0)
                {
                   //do staff
                } 
            }
于 2017-02-09T22:30:50.063 回答