Android微调:在初始化过程中避免onItemSelected调用
我用Spinner
和TextView
创build了Android应用程序。 我的任务是从TextView中的微调控制器的下拉列表中显示选定的项目。 我在onCreate
方法中实现了Spinner,所以当我运行程序的时候,它在TextView
显示一个值(在从下拉列表中select一个项目之前)。
我只想从下拉列表中select一个项目后,才显示TextView中的值。 我该怎么做呢?
这是我的代码:
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class GPACal01Activity extends Activity implements OnItemSelectedListener { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Spinner spinner = (Spinner) findViewById(R.id.noOfSubjects); // Create an ArrayAdapter using the string array and a default spinner layout ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.noofsubjects_array, android.R.layout.simple_spinner_item); // Specify the layout to use when the list of choices appears adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Apply the adapter to the spinner spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); } public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) { TextView textView = (TextView) findViewById(R.id.textView1); String str = (String) parent.getItemAtPosition(pos); textView.setText(str); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }
spinner.setOnItemSelectedListener(this); // Will call onItemSelected() Listener.
所以第一次用任何Integer值来处理
例子:初始取int check = 0;
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) { if(++check > 1) { TextView textView = (TextView) findViewById(R.id.textView1); String str = (String) parent.getItemAtPosition(pos); textView.setText(str); } }
你可以用布尔值来做,也可以通过检查当前和之前的位置。 看这里
从API级别3开始,您可以在具有布尔值的Activity上使用onUserInteraction()来确定用户是否正在与设备进行交互。
http://developer.android.com/reference/android/app/Activity.html#onUserInteraction();
@Override public void onUserInteraction() { super.onUserInteraction(); userIsInteracting = true; }
作为活动的一个领域,我有:
private boolean userIsInteracting;
最后,我的微调:
mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) { spinnerAdapter.setmPreviousSelectedIndex(position); if (userIsInteracting) { updateGUI(); } } @Override public void onNothingSelected(AdapterView<?> arg0) { } });
当你经过这个活动时,布尔值被重置为false。 奇迹般有效。
只需在设置OnItemSelectedListener之前放置这一行即可
spinner.setSelection(0,false)
哈哈…我有同样的问题。 当initViews()就这样做时,序列是关键,听者是最后一个。 祝你好运 !
spinner.setAdapter(adapter); spinner.setSelection(position); spinner.setOnItemSelectedListener(listener);
我的解决scheme
protected boolean inhibit_spinner = true; @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int pos, long arg3) { if (inhibit_spinner) { inhibit_spinner = false; }else { if (getDataTask != null) getDataTask.cancel(true); updateData(); } }
你可以这样做:
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { //set the text of TextView } @Override public void onNothingSelected(AdapterView<?> adapterView) { } }); yourSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { yourSpinner.setOnItemSelectedListener(listener); } @Override public void onNothingSelected(AdapterView<?> adapterView) { } });
起初,我创build了一个监听器,并将其归因于一个可变的callback函数; 那么我创build第二个侦听器匿名,当这是第一次被调用,这改变了侦听器=]
这对我有效
微调在Android中的初始化是有问题的,有时上述问题是通过这种模式解决的。
Spinner.setAdapter(); Spinner.setSelected(false); // must Spinner.setSelection(0,true); //must Spinner.setonItemSelectedListener(this);
设置适配器应该是第一部分,onItemSelectedListener(this)在初始化一个微调器时将是最后一个。 通过上面的模式我的OnItemSelected()没有被调用在初始化微调
启用多个spinners的类似的简单解决scheme是将AdapterView放入一个集合中(在Activity超类中),首先执行onItemSelected(…)然后在执行之前检查AdapterView是否在集合中。 这将启用超类中的一组方法,并支持多个AdapterView和多个spinners。
超级…
private Collection<AdapterView> AdapterViewCollection = new ArrayList<AdapterView>(); protected boolean firstTimeThrough(AdapterView parent) { boolean firstTimeThrough = ! AdapterViewCollection.contains(parent); if (firstTimeThrough) { AdapterViewCollection.add(parent); } return firstTimeThrough; }
子类…
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (! firstTimeThrough(parent)) { String value = safeString(parent.getItemAtPosition(pos).toString()); String extraMessage = EXTRA_MESSAGE; Intent sharedPreferencesDisplayIntent = new Intent(SharedPreferencesSelectionActivity.this,SharedPreferencesDisplayActivity.class); sharedPreferencesDisplayIntent.putExtra(extraMessage,value); startActivity(sharedPreferencesDisplayIntent); } // don't execute the above code if its the first time through // do to onItemSelected being called during view initialization.
}
有同样的问题,这对我的作品:
我有2个spinners,我在初始化和与其他控件交互期间或者从服务器获取数据之后更新它们。
这是我的模板:
public class MyClass extends <Activity/Fragment/Whatever> implements Spinner.OnItemSelectedListener { private void removeSpinnersListeners() { spn1.setOnItemSelectedListener(null); spn2.setOnItemSelectedListener(null); } private void setSpinnersListeners() { new Handler().postDelayed(new Runnable() { @Override public void run() { spn1.setOnItemSelectedListener(MyClass.this); spn2.setOnItemSelectedListener(MyClass.this); } }, 1); } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // Your code here } @Override public void onNothingSelected(AdapterView<?> parent) { } }
当类正在启动时使用setSpinnersListeners()而不是直接设置侦听器。
Runnable将会防止微调者在你设置了它们的值之后立即触发ItemSelected。
如果您需要更新微调(在服务器调用之后) ,请在更新行之前使用removeSpinnersListeners() ,并在更新行之后使用setSpinnersListeners() 。 这将防止onItemSelected在更新后触发。
你可以先通过setOnTouchListener来实现,然后在onTouch中设置setOnItemSelectedListener
@Override public boolean onTouch(final View view, final MotionEvent event) { view.setOnItemSelectedListener(this) return false; }
然后,用户交互标志可以在onTouch方法中设置为true,并在select更改处理后在onItemSelected()
重置。 我更喜欢这个解决scheme,因为用户交互标志是专门为微调控件处理的,而不是活动中的其他视图可能会影响所需的行为。
在代码中:
创build您的侦听器的侦听器:
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) { userSelect = false; // Your selection handling code here } } }
将侦听器作为OnItemSelectedListener
和OnTouchListener
添加到微调器:
SpinnerInteractionListener listener = new SpinnerInteractionListener(); mSpinnerView.setOnTouchListener(listener); mSpinnerView.setOnItemSelectedListener(listener);