如何在按代码设置所选项时禁用onItemSelectedListener

Zor*_*did 33 android listener spinner

只是想知道如何处理以下问题:根据两个微调器的选定项目计算结果.为了处理UI事物,即用户在其中一个微调器中选择一个新项目,我setOnItemSelectedListener在我onCreate()的活动方法中为旋转器安装了一个监听器.

现在:当然,这很好.听众的工作是触发结果的新计算.

问题:因为我拦截onPause() onResume()了保存/恢复最后一个状态,我得到了一个方法,可以像这里一样以编程方式设置这两个微调器的选定项:

startSpinner.setSelection(pStart);
destSpinner.setSelection(pDest);
Run Code Online (Sandbox Code Playgroud)

这两个调用也会调用侦听器!我的结果的计算方法加上新结果集的通知在这里被调用两次!

一个愚蠢的直接方法就是让一个布尔变量禁用侦听器在里面做的任何事情,在设置所选项目之前设置它并在之后重置它.好的.但是有更好的方法吗?

我不希望通过代码操作来调用侦听器,只能通过用户操作来调用!:-(

你怎么做呢?谢谢!

小智 45

在我看来,更清晰的解决方案是区分程序化和用户启动的更改,如下所示:

作为OnTouchListener和OnItemSelectedListener创建微调器的侦听器

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

}
Run Code Online (Sandbox Code Playgroud)

将侦听器添加到微调器注册两种事件类型

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
Run Code Online (Sandbox Code Playgroud)

这样,将忽略由于初始化或重新初始化而对处理程序方法的任何意外调用.

  • 绝对是我见过的最好的解决方案.有时我希望Spinner不被批评! (5认同)
  • 如果用户"触摸"视图[但不改变数据],稍后如果应用程序设置微调器,则失败 - 然后执行侦听器 (3认同)

Zor*_*did 11

好的,我按照我现在想要的方式工作.

这里要理解的事情(当我写这个问题时我没有这样做)是Android中的所有内容都在一个线程中运行 - UI线程.

含义:即使您在此处设置Spinner的值:它们仅在视觉上更新,并且只有您当前所有方法(例如onCreate,onResume或其他任何方法)完成才会调用它们的侦听器.

这允许以下内容:

  • 将所选位置保留在字段变量中.(如currentPos1,currentPos2)
  • 听众会onItemSelectedListener()调用类似的方法refreshMyResult()或其他方法.
  • 以编程方式设置位置时,设置微调器在此之后手动调用自己的刷新方法.

refreshMyResult()方法如下所示:

int newPos1 = mySpinner1.getSelectedItemPosition();
int newPos2 = mySpinner2.getSelectedItemPosition();
// only do something if update is not done yet
if (newPos1 != currentPos1 || newPos2 != currentPos2) {
    currentPos1 = newPos1;
    currentPos2 = newPos2;

    // do whatever has to be done to update things!

}
Run Code Online (Sandbox Code Playgroud)

因为稍后将调用侦听器 - 到那时,currentPos中记住的位置已经更新 - 不会发生任何事情,也不会发生任何其他事情的不必要更新.当用户在其中一个微调器中选择一个新值时,将会相应地执行更新!

而已!:-)

啊 - 还有一件事:我的问题的答案是:不会.听众不能被禁用(很容易)并且每当值发生变化时都会被调用.

  • 我使用onCheckChanged遇到了类似的问题,我解决它的方法是使用buttonView的isPressed方法验证用户输入是否正在调用代码.所以尊重,我认为你的方法可能是不明智的,除非我误解了这个问题.查看验证它是由用户调用而不是onPause()和onResume()方法. (2认同)

Ved*_*hat 6

我有一个更容易的,我认为更好的解决方案.由于我必须在初始化后刷新微调器,这是一种更通用的方法.请参考接受的答案:

不受欢迎的onItemSelected调用