我知道这个问题已被多次回答,但我没有发现任何一个问题令人满意,当然也不优雅。
问题是OnItemSelected不仅在用户选择项目时被触发,而且在以编程方式设置选择时也被触发。
有些答案建议在程序员为微调器设置值时设置一个标志。但是,有时其他Android代码会将值设置在代码之外。
android设置值的常见位置是在实例化微调器时。一些答案解决了这一特定问题。但是,有很多地方会破坏Android并重新实现微调器。追踪所有这些并不优雅。
所以问题是:如何将OnItemSelectedListener代码仅附加到用户与UI交互所做的选择?
接下来的地方是扩展Spinner并开始重写方法,但这当然意味着搞乱API(我不想做,或者我至少想让其他用户与我一起工作)
答案 0 :(得分:2)
所以我发布了一个答案,但欢迎任何批评,改进或其他更优雅的答案。
关键是重写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;
}
}
答案 1 :(得分:0)
iOS中的某些UI组件存在类似的问题。我决定使用类似的技巧。
因此,在拥有微调框的对象中的某个位置(可能是活动)声明了一个成员变量:private var isSelectionFromTouch: Boolean = false
其余相关代码:
init {
spinner.onItemSelectedListener = this
spinner.setOnTouchListener { _, _ ->
this.isSelectionFromTouch = true
false
}
}
// On Item Selected
override
fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
if (!isSelectionFromTouch) { return }
Log.d(TAG, "item selected. do something.")
isSelectionFromTouch = false
}
override
fun onNothingSelected(parent: AdapterView<*>?) {
isSelectionFromTouch = false
}