Android Spinner OnItemSelected 仅在用户交互时

标签 android spinner user-interaction onitemselectedlistener

我知道这个问题已被多次回答,但我没有发现任何令人满意的答案,当然也不优雅。

问题是 OnItemSelected 不仅会在用户选择项目时触发,还会在以编程方式设置选择时触发。

一些答案​​建议在程序员为微调器设置值时设置一个标志。然而,有时其他 Android 代码会在您的代码之外设置值。

android 设置值的常见位置是在微调器实例化时。一些答案解决了该特定问题。但是,Android 会在很多地方崩溃并重新实例化微调器。追踪所有这些并不优雅。

所以问题是:如何将他们的 OnItemSelectedListener 代码仅附加到用户与 UI 交互所做的选择?

  • Spinner.setOnItemClickListener 似乎可以完美地回答这个问题,但 Google 已将其禁用
  • AdapterView.setOnClickListener 看起来也很自然,但它也会产生运行时错误

下一个地方是扩展 Spinner 并开始覆盖方法,但这当然意味着弄乱 API(我宁愿不这样做,或者我至少希望其他用户与我一起工作)

最佳答案

所以我发布了一个答案,但欢迎任何批评、改进或其他更优雅的答案。

关键是覆盖 onClick 以设置一个标志,该标志将 onItemSelectedListener 与用户交互联系起来并触发 onItemClickedListener。

如果您不习惯使用 API setOnItemClickedListener(也许是为了将来的兼容性),您当然可以替换为您自己的方法。我只是觉得 onItemClickedListener 应该一直实现这种效果,所以这是我微妙的抗议。

此外,如果有人能想到 spinnerTouched 标志短路的原因(保持真实的时间超过应有的时间),请告诉我们以便解决该问题。到目前为止,它似乎工作得很好。

public class OnItemClickSpinner extends Spinner implements AdapterView.OnItemSelectedListener {

    boolean spinnerTouched = false;
    OnItemClickListener onItemClickListener = null;
    OnItemSelectedListener onItemSelectedListener = null;

    public OnItemClickSpinner(Context context) {
        super(context);
        super.setOnItemSelectedListener(this);
    }

    public OnItemClickSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setOnItemSelectedListener(this);
    }

    public OnItemClickSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        super.setOnItemSelectedListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        spinnerTouched = true;
        return super.onTouchEvent(event);
    }

    @Override
    public void setOnItemClickListener(OnItemClickListener listener) {
        onItemClickListener = listener;
    }

    @Override
    public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
        this.onItemSelectedListener = onItemSelectedListener;
        super.setOnItemSelectedListener(this);
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if(spinnerTouched && this.onItemClickListener!=null) this.onItemClickListener.onItemClick(parent,view,position,id);
        if(this.onItemSelectedListener!=null) this.onItemSelectedListener.onItemSelected(parent,view,position,id);
        spinnerTouched=false;
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        if(this.onItemSelectedListener!=null) this.onItemSelectedListener.onNothingSelected(parent);
        spinnerTouched=false;
    }
}

关于Android Spinner OnItemSelected 仅在用户交互时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27193962/

相关文章:

android - 如果我在Firebase身份验证中使用Facebook登录,为什么我的currentUser始终为null?

android - 在 Android 中使用 SimpleAdapter 填充 Spinner

android微调器宽度问题?

ios - 将用户交互锁定到 WKWebView

java - 检测自上次用户与应用程序交互以来的时间

c# - SignalR 连接线程与 Android

android - 在视频开始播放之前添加 "please wait loading...."

android - DialogFragment show() 方法中的错误

android - 单击时弹出窗口中的错误微调器

java - JUnit 询问用户测试是否成功?