Android 微调器被错误地调用(没有用户操作)

Android 微调器被错误地调用(没有用户操作),android,spinner,android-spinner,Android,Spinner,Android Spinner,我有一个在对话框视图中显示的微调器,对话框启动的那一刻即被调用。我真的不想处理这个,但只有当用户做出选择时。因此,我需要防止这种情况发生(可能是因为没有设置默认值?),或者我需要知道不是用户做出了选择?是的,您看到的是正确的,是默认行为,您无法防止这种情况发生。初始加载时调用OnItemSelected回调。在初始加载之后,只有当用户更改选择或您从代码中更改选择时,才会触发该选项。您可以有一个指示器,它可以告诉您事件是否是初始加载的结果,如果您不想处理它,则可以忽略第一个事件 Androider

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

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

Androider,我已经找到了这个问题的解决方案,并将其发布在这里(带有代码示例):


我用另一种方法解决了这个问题,因为我注意到有时在方向更改时调用两次或一次onItemSelected方法

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

widgetsRestartTime声明为double和intance变量

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

我还在互联网上寻找一个好的解决方案,但没有找到任何能满足我需求的解决方案。 因此,我在Spinner类上编写了这个扩展,因此您可以设置一个简单的Listener,它与ListView具有相同的行为

只有当一个项目被“选中”时,才会调用McClickListener

玩得开心

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

您只需添加一个int计数即可解决此问题:)

sp.setOnItemSelectedListener(新的OnItemSelectedListener(){
整数计数=0;
@凌驾
已选择公共视图(AdapterView arg0、视图arg1、内部arg2、长arg3){
如果(计数>=1){
int item=sp.getSelectedItemPosition();
Toast.makeText(getBaseContext(),
您已选择书籍:“+androidBooks[项目],
吐司。长度(短)。show();
}
计数++;
}
@凌驾
未选择公共无效(AdapterView arg0){
}
});

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

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

我找到了另一个解决方案,不过:

  • 在初始化微调器时,在活动的onCreate()或片段的onCreateView中,以及在设置侦听器之前,在微调器上设置默认标记
  • 在侦听器中,检查标记(如果存在),然后通过返回将其删除,不执行代码。
  • 就是这样,它就像一个符咒

    侦听器中的示例:

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

    另外,这适用于设置为多个微调器的同一侦听器

    如果你也在买一个,你可以一起去

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if(pos != 0) {
            pos--;
    
            // your code here
        }
    }
    
    @覆盖
    已选择公共位置(AdapterView父项、视图、整数位置、长id){
    如果(位置!=0){
    pos--;
    //你的代码在这里
    }
    }
    

    因为项目0永远无法选择。干杯:-)

    从API级别3开始,您可以对带有布尔值的活动使用onUserInteraction(),以确定用户是否正在与设备交互

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

    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) {
    
            }
        });
    
    mSpinnerView.setOnItemSelectedListener(新的OnItemSelectedListener(){
    @凌驾
    已选择公共位置(AdapterView arg0、视图、整型位置、长arg3){
    spinnerAdapter.setmPreviousSelectedIndex(位置);
    如果(用户交互){
    updateGUI();
    }
    }
    @凌驾
    未选择公共无效(AdapterView arg0){
    }
    });
    
    当您在活动中来回走动时,布尔值将重置为false。工作起来很有魅力。

    对我来说很有效

    private boolean isspinnerinital=true

    @Override
    public void onItemSelected(AdapterView<?> parent, View view,
            int position, long id) {
    
        if(isSpinnerInitial)
        {
            isSpinnerInitial = false;
        }
        else  {
            // do your work...
        }
    
    }
    
    @覆盖
    已选择公共视图(AdapterView父视图、视图、,
    内部位置,长id){
    如果(初始值)
    {
    isSpinnerInitial=false;
    }
    否则{
    //做你的工作。。。
    }
    }
    
    比尔·莫特解决方案的另一个选择是使
    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;
            }
        }
    
    }
    

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

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

    如果你不介意使用promt的职位,那么每次你想在spinner上工作时,你都可以这样做。promt的第一组选择:

    spinner.setselected(0);
    spinner.add("something");
    ...
    
    然后在选择发生时执行类似操作:

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

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

    spinner.setSelection(count, false);
    

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

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