我想到了一些不太优雅的方法来解决这个问题,但我知道我必须遗漏一些东西。
我的onItemSelected
会立即触发,而不会与用户进行任何交互,这是不受欢迎的行为。 我希望UI等到用户选择之前做任何事情。
我甚至尝试在onResume()
设置监听器,希望这会有所帮助,但事实并非如此。
如何在用户触摸控件之前停止此操作?
public class CMSHome extends Activity {
private Spinner spinner;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Heres my spinner ///////////////////////////////////////////
spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.pm_list, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
};
public void onResume() {
super.onResume();
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
Intent i = new Intent(CMSHome.this, ListProjects.class);
i.putExtra("bEmpID", parent.getItemAtPosition(pos).toString());
startActivity(i);
Toast.makeText(parent.getContext(), "The pm is " +
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
}
#1楼
带有布尔标志或计数器的解决方案对我没有帮助,因为在方向改变时onItemSelected()调用“overflew”标志或计数器。
我将android.widget.Spinner
子类化,并做了一些微小的补充。 相关部分如下。 这个解决方案对我有用。
private void setHandleOnItemSelected()
{
final StackTraceElement [] elements = Thread.currentThread().getStackTrace();
for (int index = 1; index < elements.length; index++)
{
handleOnItemSelected = elements[index].toString().indexOf("PerformClick") != -1; //$NON-NLS-1$
if (handleOnItemSelected)
{
break;
}
}
}
@Override
public void setSelection(int position, boolean animate)
{
super.setSelection(position, animate);
setHandleOnItemSelected();
}
@Override
public void setSelection(int position)
{
super.setSelection(position);
setHandleOnItemSelected();
}
public boolean shouldHandleOnItemSelected()
{
return handleOnItemSelected;
}
#2楼
我创建了一个小实用程序方法来更改Spinner
选择而不通知用户:
private void setSpinnerSelectionWithoutCallingListener(final Spinner spinner, final int selection) {
final OnItemSelectedListener l = spinner.getOnItemSelectedListener();
spinner.setOnItemSelectedListener(null);
spinner.post(new Runnable() {
@Override
public void run() {
spinner.setSelection(selection);
spinner.post(new Runnable() {
@Override
public void run() {
spinner.setOnItemSelectedListener(l);
}
});
}
});
}
它会禁用侦听器,更改选择,然后重新启用侦听器。
诀窍是调用与UI线程异步,因此您必须在连续的处理程序帖子中执行此操作。
#3楼
我处于类似的情况,我有一个简单的解决方案为我工作。
似乎方法setSelection(int position)
和setSelected(int position, boolean animate)
具有不同的内部实现。
当您使用带有false animate标志的第二个方法setSelected(int position, boolean animate)
时,您将获得选择而不触发onItemSelected
侦听器。
#4楼
我找到了更优雅的解决方案。 它涉及计算调用ArrayAdapter(在您的情况下为“适配器”)的次数。 假设您有1个微调器并且您调用:
int iCountAdapterCalls = 0;
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.pm_list, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
在onCreate之后声明一个int计数器,然后在onItemSelected()方法内部放置一个“if”条件来检查atapter被调用了多少次。 在你的情况下,你只需要调用一次:
if(iCountAdapterCalls < 1)
{
iCountAdapterCalls++;
//This section executes in onCreate, during the initialization
}
else
{
//This section corresponds to user clicks, after the initialization
}
#5楼
不幸的是,似乎这个问题的两个最常见的建议解决方案,即计算回调事件和发布Runnable以便稍后设置回调,例如在启用可访问性选项时都会失败。 这是一个解决这些问题的助手类。 进一步的explenation在注释块中。
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
/**
* Spinner Helper class that works around some common issues
* with the stock Android Spinner
*
* A Spinner will normally call it's OnItemSelectedListener
* when you use setSelection(...) in your initialization code.
* This is usually unwanted behavior, and a common work-around
* is to use spinner.post(...) with a Runnable to assign the
* OnItemSelectedListener after layout.
*
* If you do not call setSelection(...) manually, the callback
* may be called with the first item in the adapter you have
* set. The common work-around for that is to count callbacks.
*
* While these workarounds usually *seem* to work, the callback
* may still be called repeatedly for other reasons while the
* selection hasn't actually changed. This will happen for
* example, if the user has accessibility options enabled -
* which is more common than you might think as several apps
* use this for different purposes, like detecting which
* notifications are active.
*
* Ideally, your OnItemSelectedListener callback should be
* coded defensively so that no problem would occur even
* if the callback was called repeatedly with the same values
* without any user interaction, so no workarounds are needed.
*
* This class does that for you. It keeps track of the values
* you have set with the setSelection(...) methods, and
* proxies the OnItemSelectedListener callback so your callback
* only gets called if the selected item's position differs
* from the one you have set by code, or the first item if you
* did not set it.
*
* This also means that if the user actually clicks the item
* that was previously selected by code (or the first item
* if you didn't set a selection by code), the callback will
* not fire.
*
* To implement, replace current occurrences of:
*
* Spinner spinner =
* (Spinner)findViewById(R.id.xxx);
*
* with:
*
* SpinnerHelper spinner =
* new SpinnerHelper(findViewById(R.id.xxx))
*
* SpinnerHelper proxies the (my) most used calls to Spinner
* but not all of them. Should a method not be available, use:
*
* spinner.getSpinner().someMethod(...)
*
* Or just add the proxy method yourself :)
*
* (Quickly) Tested on devices from 2.3.6 through 4.2.2
*
* @author Jorrit "Chainfire" Jongma
* @license WTFPL (do whatever you want with this, nobody cares)
*/
public class SpinnerHelper implements OnItemSelectedListener {
private final Spinner spinner;
private int lastPosition = -1;
private OnItemSelectedListener proxiedItemSelectedListener = null;
public SpinnerHelper(Object spinner) {
this.spinner = (spinner != null) ? (Spinner)spinner : null;
}
public Spinner getSpinner() {
return spinner;
}
public void setSelection(int position) {
lastPosition = Math.max(-1, position);
spinner.setSelection(position);
}
public void setSelection(int position, boolean animate) {
lastPosition = Math.max(-1, position);
spinner.setSelection(position, animate);
}
public void setOnItemSelectedListener(OnItemSelectedListener listener) {
proxiedItemSelectedListener = listener;
spinner.setOnItemSelectedListener(listener == null ? null : this);
}
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position != lastPosition) {
lastPosition = position;
if (proxiedItemSelectedListener != null) {
proxiedItemSelectedListener.onItemSelected(
parent, view, position, id
);
}
}
}
public void onNothingSelected(AdapterView<?> parent) {
if (-1 != lastPosition) {
lastPosition = -1;
if (proxiedItemSelectedListener != null) {
proxiedItemSelectedListener.onNothingSelected(
parent
);
}
}
}
public void setAdapter(SpinnerAdapter adapter) {
if (adapter.getCount() > 0) {
lastPosition = 0;
}
spinner.setAdapter(adapter);
}
public SpinnerAdapter getAdapter() { return spinner.getAdapter(); }
public int getCount() { return spinner.getCount(); }
public Object getItemAtPosition(int position) { return spinner.getItemAtPosition(position); }
public long getItemIdAtPosition(int position) { return spinner.getItemIdAtPosition(position); }
public Object getSelectedItem() { return spinner.getSelectedItem(); }
public long getSelectedItemId() { return spinner.getSelectedItemId(); }
public int getSelectedItemPosition() { return spinner.getSelectedItemPosition(); }
public void setEnabled(boolean enabled) { spinner.setEnabled(enabled); }
public boolean isEnabled() { return spinner.isEnabled(); }
}
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3163671