Spinner onItemSelected错误地调用(无需用户操作)

时间:2011-02-26 03:24:27

标签: android spinner android-spinner

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

15 个答案:

答案 0 :(得分:41)

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;
        }
    }

}

将监听器添加为微调器OnItemSelectedListenerOnTouchListener

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);

答案 1 :(得分:21)

你可以简单地添加一个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) {
    }
});

答案 2 :(得分:8)

从API级别3开始,您可以在具有布尔值的Activity上使用onUserInteraction()来确定用户是否正在与设备进行交互。

http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    userIsInteracting = true;
}

作为我所拥有的活动的一个字段:

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。像魅力一样。

答案 3 :(得分:6)

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

Spinner onItemSelected() executes when it is not suppose to

答案 4 :(得分:4)

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

这似乎取决于当前的微调器选择。因此,旗帜或柜台对我不起作用。相反,我用BOTH onResume()和onCreate记录系统时间     widgetsRestartTime = System.currentTimeMillis()

widgetsRestartTime被声明为double和intance变量。

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

答案 5 :(得分:3)

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

答案 6 :(得分:3)

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

答案 7 :(得分:3)

我遇到了同样的问题。但是接受的解决方案并不适用于我,因为我的表单上有多个微调器,其中一些是隐藏的,当旋转器被隐藏时,监听器不会触发,因此计数对我来说不是解决方案。

我找到了另一种解决方案

  1. 在初始化时在微调器上设置默认TAG,在活动的onCreate()或片段的onCreateView上设置默认TAG,然后再设置监听器
  2. 在侦听器中,检查标记,如果存在,则删除它,不要执行代码,方法是返回。
  3. 就是这样,它就像一个魅力!

    监听器中的示例:

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

    P.S。这适用于设置为多个微调器的同一个监听器!

答案 8 :(得分:2)

如果您还在购买initially unselected Spinner,则可以使用

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

        // your code here
    }
}

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

答案 9 :(得分: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...
    }

}

答案 10 :(得分: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());
        }
    }
}

答案 11 :(得分:1)

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

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);

答案 12 :(得分:1)

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

spinner.setSelection(count, false);

所以,把它放在OnItemSelectedListener:

之前
spinner.setSelection(0,false);

您可以从开发者页面查看更多内容:

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

答案 13 :(得分:0)

如果你不介意使用某个职位,你可以在每次想要在微调器上做员工时做这样的事情。首先选择promt:

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

然后在选择发生时做类似的事情:

spinner.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) => 
            {
                if (spinner.SelectedItemPosition != 0)
                {
                   //do staff
                } 
            }

答案 14 :(得分:0)

问题是我们在微调器完成渲染之前设置了侦听器。一旦呈现,它会自动选择它的数据集第一个选项(这很好),但这会导致我们的侦听器触发。

解决办法是等待特定的spinner布局好,然后才设置监听器:

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) {

            }
        });
    }
});