我有36个微调器,我用一些值初始化了。我用过onItemSelectedListener。像往常一样,用户可以与这些微调器进行交互,触发onItemSeected函数。
一个问题是调用是在init期间进行的,但我在这里找到了解决方案并避免使用全局变量“count”并检查count> 36在onItemSelected中执行代码之前。
我的问题是: 用户可以选择单击名为“Previous”的按钮,我必须重置一些微调器值。
我尝试在重置微调器之前将count的值更改为0,然后在重置后将其更改回37,但我已经明白只有在每个其他函数执行完毕后才调用onItemSelected,所以它是即使微调器值在用户选择后立即设置,AFTER计数也会更改回37.
我需要重复刷新一些微调器而不触发onItemSelected函数。有谁能帮我找到解决方案?感谢。
答案 0 :(得分:64)
我找到了一个简单的,我认为优雅的解决方案。 使用标签。 我首先创建了一个名为“tags”的新XML文件,并输入以下代码:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item name="pos" type="id" />
</resources>
每当我自己使用spin.setSelection(pos)
时,我也会spin.setTag(R.id.pos, pos)
,所以我将当前位置设置为标记。
然后,在onItemSelected中,我只执行代码if(spin.getTag(R.id.pos) != position)
,其中position是函数提供的位置变量。
这样,我的代码仅在用户进行选择时执行。
由于用户已进行选择,因此标签尚未更新,因此在处理完成后,我将标记更新为spin.setTag(R.id.pos, position)
。
注意:始终使用相同的适配器很重要,或者“position”变量可能指向不同的元素。
编辑:正如kaciula指出的那样,如果您没有使用多个标签,则可以使用更简单的版本,即spin.setTag(pos)
和spin.getTag()
,而无需使用一个XML文件。
答案 1 :(得分:14)
当使用Spinner.setSelection(position)时,它总是激活setOnItemSelectedListener()
为避免触发代码两次,我使用此解决方案:
private Boolean mIsSpinnerFirstCall = true;
...
Spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//If a new value is selected (avoid activating on setSelection())
if(!mIsSpinnerFirstCall) {
// Your code goes gere
}
mIsSpinnerFirstCall = false;
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
答案 2 :(得分:3)
我不知道这个解决方案是否像这里选择的解决方案一样简单,但它对我来说效果很好,看起来更简单:
boolean executeOnItemSelected = false;
spinner.setSelection(pos)
然后在OnItemSelectedListener
中public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(executeOnItemSelected){
//Perform desired action
} else {
executeOnItemSelected = true;
}
}
答案 3 :(得分:2)
我解决这个问题的方法是先保存OnItemSelectedListener。然后将Spinner的OnItemSelectedListener设置为空值。按代码在Spinner中设置项目后,再次还原OnItemSelectedListener。这对我有用。
见下面的代码:
// disable the onItemClickListener before changing the selection by code. Set it back again afterwards
AdapterView.OnItemSelectedListener onItemSelectedListener = historyPeriodSpinner.getOnItemSelectedListener();
historyPeriodSpinner.setOnItemSelectedListener(null);
historyPeriodSpinner.setSelection(0);
historyPeriodSpinner.setOnItemSelectedListener(onItemSelectedListener);
答案 4 :(得分:1)
这是我解决这个问题的方法。我扩展AppCompatSpinner
并添加方法pgmSetSelection(int pos)
,允许编程选择设置而不触发选择回调。我用RxJava对此进行了编码,以便通过Observable
传递选择事件。
package com.controlj.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import io.reactivex.Observable;
/**
* Created by clyde on 22/11/17.
*/
public class FilteredSpinner extends android.support.v7.widget.AppCompatSpinner {
private int lastSelection = INVALID_POSITION;
public void pgmSetSelection(int i) {
lastSelection = i;
setSelection(i);
}
/**
* Observe item selections within this spinner. Events will not be delivered if they were triggered
* by a call to setSelection(). Selection of nothing will return an event equal to INVALID_POSITION
*
* @return an Observable delivering selection events
*/
public Observable<Integer> observeSelections() {
return Observable.create(emitter -> {
setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if(i != lastSelection) {
lastSelection = i;
emitter.onNext(i);
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
onItemSelected(adapterView, null, INVALID_POSITION, 0);
}
});
});
}
public FilteredSpinner(Context context) {
super(context);
}
public FilteredSpinner(Context context, int mode) {
super(context, mode);
}
public FilteredSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FilteredSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FilteredSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
super(context, attrs, defStyleAttr, mode);
}
}
其用法示例,例如在onCreateView()
的{{1}}中调用:
Fragment
其中 mySpinner = view.findViewById(R.id.history);
mySpinner.observeSelections()
.subscribe(this::setSelection);
是封闭视图中的方法,看起来像这样,并且通过setSelection()
从用户选择事件调用,也可以通过编程方式调用,因此处理选择的逻辑很常见两种选择方法。
Observable