Как сделать так, чтобы onItemSelected не запускался при создании нового экземпляра Spinner?
-
23-09-2019 - |
Вопрос
Я думал о нескольких не слишком элегантных способах решения этой проблемы, но я знаю, что, должно быть, чего-то не хватает.
Мой onItemSelected
запускается немедленно без какого-либо взаимодействия с пользователем, и это нежелательное поведение.Я хочу, чтобы пользовательский интерфейс подождал, пока пользователь что-то выберет, прежде чем что-либо делать.
Я даже попробовал настроить прослушиватель в 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.
}
}
}
Решение
Я бы ожидал, что ваше решение будет работать - я, хотя событие выбора не будет стрелять, если вы установите адаптер перед настройкой слушателя.
При этом простой логический флаг позволит вам обнаружить событие первого отбора Rogue и игнорировать его.
Другие советы
Использование Runnables совершенно неверно.
Использовать setSelection(position, false);
В начальном выборе перед setOnItemSelectedListener(listener)
Таким образом, вы устанавливаете свой выбор без анимации, которая приводит к названию выбранного прослушивателя на INTER. Но слушатель нулевой, поэтому ничего не работает. Тогда ваш слушатель назначен.
Так что следуйте этой точной последовательности:
Spinner s = (Spinner)Util.findViewById(view, R.id.sound, R.id.spinner);
s.setAdapter(adapter);
s.setSelection(position, false);
s.setOnItemSelectedListener(listener);
Ссылаясь на ответ Дэна Дайера, попробуйте зарегистрировать OnSelectListener
в post(Runnable)
Метод:
spinner.post(new Runnable() {
public void run() {
spinner.setOnItemSelectedListener(listener);
}
});
Сделав это для меня, желательное поведение наконец произошло.
В этом случае это также означает, что слушатель стреляет только на измененный элемент.
Я создал небольшой метод утилиты для изменения 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);
}
});
}
});
}
Он отключает слушателя, меняет выбор и после этого заново уводит слушателя.
Хитрость заключается в том, что звонки асинхронны по отношению к потоке пользовательского интерфейса, поэтому вы должны сделать это в последовательных постах обработчиков.
К сожалению, кажется, что два наиболее часто предлагаемых решения этой проблемы, а именно, подсчет возникновения вызовов и публикация запуска, чтобы установить обратный вызов в более позднее время, оба могут обанкротиться, когда, например, параметры доступности. Вот помощник, который работает по этим вопросам. Дальнейшее объяснение в блоке комментариев.
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(); }
}
У меня было много проблем с стрельбой из прядильщика, когда я этого не хотел, и все ответы здесь ненадежны. Они работают - но только иногда. В конечном итоге вы столкнетесь с сценариями, в которых они потерпят неудачу, и введут ошибки в ваш код.
Для меня сработало хранить последний выбранный индекс в переменной и оценить его у слушателя. Если это то же самое, что и новый выбран, ничего не делает, и вернуться, иначе продолжайте со слушателем. Сделай это:
//Declare a int member variable and initialize to 0 (at the top of your class)
private int mLastSpinnerPosition = 0;
//then evaluate it in your listener
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if(mLastSpinnerPosition == i){
return; //do nothing
}
mLastSpinnerPosition = i;
//do the rest of your code now
}
Поверьте мне, когда я говорю это, это, безусловно, самое надежное решение. Хак, но это работает!
Я был в аналогичной ситуации, и у меня есть простое решение для меня.
Это кажется методами setSelection(int position)
а также setSelected(int position, boolean animate)
иметь различную внутреннюю реализацию.
Когда вы используете второй метод setSelected(int position, boolean animate)
С флагом False Animate вы получаете выбор без стрельбы onItemSelected
слушатель.
Просто чтобы установить намеки на использование OnTouchListener для различения автоматических вызовов в SetOnIteMeSelectedListener (которые являются частью инициализации активности и т. Д.), против его вызовов, вызванных фактическим взаимодействием пользователя, я сделал следующее после некоторых других предложений здесь и здесь и обнаружил, что это хорошо сработало с наименьшим количеством строк кода.
Просто установите логическое поле для вашей активности/фрагмента, как:
private Boolean spinnerTouched = false;
Затем, как раз перед тем, как установить SetOniteMelectedListener вашего Spinner, установите OnTouchListener:
spinner.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("Real touch felt.");
spinnerTouched = true;
return false;
}
});
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
...
if (spinnerTouched){
//Do the stuff you only want triggered by real user interaction.
}
spinnerTouched = false;
spinner.setSelection(Adapter.NO_SELECTION, false);
После долгого вытянув волосы, я создал свой собственный класс Spinner. Я добавил метод, который соответствующим образом отключает и подключает слушателя.
public class SaneSpinner extends Spinner {
public SaneSpinner(Context context) {
super(context);
}
public SaneSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SaneSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// set the ceaseFireOnItemClickEvent argument to true to avoid firing an event
public void setSelection(int position, boolean animate, boolean ceaseFireOnItemClickEvent) {
OnItemSelectedListener l = getOnItemSelectedListener();
if (ceaseFireOnItemClickEvent) {
setOnItemSelectedListener(null);
}
super.setSelection(position, animate);
if (ceaseFireOnItemClickEvent) {
setOnItemSelectedListener(l);
}
}
}
Используйте его в своем XML, как это:
<my.package.name.SaneSpinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/mySaneSpinner"
android:entries="@array/supportedCurrenciesFullName"
android:layout_weight="2" />
Все, что вам нужно сделать, это получить экземпляр Sanespinner после инфляции и вызова набора, как это:
mMySaneSpinner.setSelection(1, true, true);
При этом ни одно событие не запущено, а взаимодействие с пользователем не прерывается. Это сильно уменьшило сложность моей кода. Это должно быть включено в стандартный Android, так как это действительно лаваш.
Никаких нежелательных событий с фазы макета, если вы отложите добавление слушателя, пока макет не будет закончен:
spinner.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Ensure you call it only once works for JELLY_BEAN and later
spinner.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// add the listener
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// check if pos has changed
// then do your work
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
});
Это произойдет, если вы делаете выбор в коде как;
mSpinner.setSelection(0);
Вместо вышеупомянутого оператора Использование
mSpinner.setSelection(0,false);//just simply do not animate it.
РЕДАКТИРОВАТЬ: Этот метод не работает для Mi Android версии Mi UI.
Я получил очень простой ответ, на 100% уверен, что он работает:
boolean Touched=false; // this a a global variable
public void changetouchvalue()
{
Touched=true;
}
// this code is written just before onItemSelectedListener
spinner.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("Real touch felt.");
changetouchvalue();
return false;
}
});
//inside your spinner.SetonItemSelectedListener , you have a function named OnItemSelected iside that function write the following code
if(Touched)
{
// the code u want to do in touch event
}
Я нашел гораздо более элегантное решение для этого. Это включает в себя подсчет того, сколько раз был вызван арест -адаптер (в вашем случае «адаптер»). Допустим, у вас есть 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);
Объявите счетчик int после того, как метод Oncreate, а затем Inside onitemselected (), установите условие «если», чтобы проверить, сколько раз называется Atapter. В вашем случае вы называете это всего один раз:
if(iCountAdapterCalls < 1)
{
iCountAdapterCalls++;
//This section executes in onCreate, during the initialization
}
else
{
//This section corresponds to user clicks, after the initialization
}
Мой небольшой вклад - это вариант некоторых из вышеперечисленных, которые подходили мне несколько раз.
Объявите целочисленную переменную как значение по умолчанию (или последнее использованное значение, сохраненное в предпочтениях). Используйте spinner.setseletection (mydefault), чтобы установить это значение до того, как слушатель будет зарегистрирован. В onitemseleded проверьте, равняется ли новое значение Spinner назначенное вами значение перед запуском какого -либо дальнейшего кода.
Это имеет дополнительное преимущество в том, что он не запускает код, если пользователь снова выбирает то же значение.
Столкнувшись с той же проблемой, я пришел к этому решению, используя теги.Идея, стоящая за этим, проста:Всякий раз, когда счетчик меняется программно, убедитесь, что метка отражает выбранную позицию.Затем в прослушивателе вы проверяете, соответствует ли выбранная позиция тегу.Если это так, значит, выбор счетчика был изменен программным путем.
Ниже приведен мой новый класс "spinner proxy":
package com.samplepackage;
import com.samplepackage.R;
import android.widget.Spinner;
public class SpinnerFixed {
private Spinner mSpinner;
public SpinnerFixed(View spinner) {
mSpinner = (Spinner)spinner;
mSpinner.setTag(R.id.spinner_pos, -2);
}
public boolean isUiTriggered() {
int tag = ((Integer)mSpinner.getTag(R.id.spinner_pos)).intValue();
int pos = mSpinner.getSelectedItemPosition();
mSpinner.setTag(R.id.spinner_pos, pos);
return (tag != -2 && tag != pos);
}
public void setSelection(int position) {
mSpinner.setTag(R.id.spinner_pos, position);
mSpinner.setSelection(position);
}
public void setSelection(int position, boolean animate) {
mSpinner.setTag(R.id.spinner_pos, position);
mSpinner.setSelection(position, animate);
}
// If you need to proxy more methods, use "Generate Delegate Methods"
// from the context menu in Eclipse.
}
Вам также понадобится XML-файл с настройкой тега в вашем Values
справочник.Я назвал свой файл spinner_tag.xml
, но это зависит от вас.Это выглядит примерно так:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item name="spinner_pos" type="id" />
</resources>
Теперь замените
Spinner myspinner;
...
myspinner = (Spinner)findViewById(R.id.myspinner);
в вашем коде с
SpinnerFixed myspinner;
...
myspinner = new SpinnerFixed(findViewById(R.id.myspinner));
И сделайте так, чтобы ваш обработчик выглядел примерно так:
myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (myspinner.isUiTriggered()) {
// Code you want to execute only on UI selects of the spinner
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Функция isUiTriggered()
вернет true тогда и только тогда, когда счетчик был изменен пользователем.Обратите внимание, что у этой функции есть побочный эффект - она установит тег, поэтому второй вызов в том же вызове прослушивателя всегда будет возвращать false
.
Эта оболочка также решит проблему с вызовом прослушивателя во время создания макета.
Веселись, Йенс.
Поскольку для меня ничего не сработало, и у меня более 1 прядильщика, по моему мнению (и IMHO, держащий карту Bool - это излишний), я использую тег, чтобы подсчитать клики:
spinner.setTag(0);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Integer selections = (Integer) parent.getTag();
if (selections > 0) {
// real selection
}
parent.setTag(++selections); // (or even just '1')
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Много ответов уже, вот моя.
Я протягиваю 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()
в Fragment
Например:
mySpinner = view.findViewById(R.id.history);
mySpinner.observeSelections()
.subscribe(this::setSelection);
куда setSelection()
это метод в обзоре, который выглядит так, и который называется оба из событий выбора пользователя через Observable
А также в других местах программно, поэтому логика для выбора обработки является общей для обоих методов выбора.
private void setSelection(int position) {
if(adapter.isEmpty())
position = INVALID_POSITION;
else if(position >= adapter.getCount())
position = adapter.getCount() - 1;
MyData result = null;
mySpinner.pgmSetSelection(position);
if(position != INVALID_POSITION) {
result = adapter.getItem(position);
}
display(result); // show the selected item somewhere
}
Я бы попытался позвонить
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
После того, как вы звоните SetAdapter (). Также попробуйте позвонить перед адаптером.
У вас всегда есть решение, чтобы пойти с подклассом, где вы можете обернуть логический флаг в свой метод переопределенного сетадаптера, чтобы пропустить событие.
Решение с логическим флагом или счетчиком не помогло мне, потому что во время ориентации изменение onitemselected () вызовы «переполняют» флаг или счетчик.
Я подкласс 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;
}
Это не элегантное решение. На самом деле это скорее Руб-Голдберг, но, похоже, работает. Я удостоверился, что прядильщик использовался хотя бы один раз, расширив адаптер массива и переопределяя его getdropdownview. В новом методе GetDropDownView у меня есть логический флаг, который настроен на то, чтобы показать выпадающее меню, по крайней мере, один раз. Я игнорирую звонки слушателю, пока флаг не будет установлен.
MainActivity.oncreate ():
ActionBar ab = getActionBar();
ab.setDisplayShowTitleEnabled(false);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ab.setListNavigationCallbacks(null, null);
ArrayList<String> abList = new ArrayList<String>();
abList.add("line 1");
...
ArAd abAdapt = new ArAd (this
, android.R.layout.simple_list_item_1
, android.R.id.text1, abList);
ab.setListNavigationCallbacks(abAdapt, MainActivity.this);
переопределить адаптер массива:
private static boolean viewed = false;
private class ArAd extends ArrayAdapter<String> {
private ArAd(Activity a
, int layoutId, int resId, ArrayList<String> list) {
super(a, layoutId, resId, list);
viewed = false;
}
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
viewed = true;
return super.getDropDownView(position, convertView, parent);
}
}
Модифицированный слушатель:
@Override
public boolean onNavigationItemSelected(
int itemPosition, long itemId) {
if (viewed) {
...
}
return false;
}
Если вам нужно воссоздать активность на лету, например: изменение тем, простой флаг/счетчик не работает
Используйте функцию OnUserInteraction () для обнаружения активности пользователя,
У меня есть Выполнено с самым простым способом:
private AdapterView.OnItemSelectedListener listener;
private Spinner spinner;
oncreate ();
spinner = (Spinner) findViewById(R.id.spinner);
listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
Log.i("H - Spinner selected position", position);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
};
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
spinner.setOnItemSelectedListener(listener);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
Сделанный
if () {
spinner.setSelection(0);// No reaction to create spinner !!!
} else {
spinner.setSelection(intPosition);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position > 0) {
// real selection
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Я мог бы получить решение моей проблемы, просто умножив ширину с 2, что было привело к коду:
CGFloat width = [ScrollingLabel.text sizeWithFont:ScrollingLabel.font].width;
ScrollingLabel.frame = CGRectMake(1024,720,width,45);
. Мне нужно использовать mSpinner
На взгляде, так что флаг mOldPosition
установлен в анонимном внутреннем классе.
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
int mOldPosition = mSpinner.getSelectedItemPosition();
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
if (mOldPosition != position) {
mOldPosition = position;
//Do something
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
//Do something
}
});
Я бы сохранил исходный индекс во время создания объекта onClickListener.
int thisInitialIndex = 0;//change as needed
myspinner.setSelection(thisInitialIndex);
myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
int initIndex = thisInitialIndex;
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (id != initIndex) { //if selectedIndex is the same as initial value
// your real onselecteditemchange event
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Вы должны быть в состоянии сделать это, не прибегая к GeneracodicCode. Как насчет:
RedirectMatch ^/$ http://www.yourdomain.com/hold/
.
см. см. Документация mod_rewrite
.
Однако вам может быть лучше настройки второй Virtualhost, поэтому вы можете установить весь общедоступный сайт в холдинг (используя что-то вроде RedirectMatch
, чтобы получить код состояния HTTP 503), но все же используйте администратор WordPress и сайт самостоятельно через другой Имя хоста. (Я не знаю, будет ли WordPress возникнут проблемы с этим; у меня есть ощущение его настойчивости к знанию домена, который он работает под тем, может привести к вам проблемы, к сожалению.)
(Я подозреваю, что вы возникаете в проблемы, потому что ваш первый генеракодицетагCode предполагает, что Gensacodicetacodcode уже произошло, хотя проходило некоторое время, поскольку я использовал RewriteRule ^.*$ /hold/ [R=503,L]
, и документация не ясна на этом. Для такой простой пары случаев Я полностью избегаю генеракодицетагкода, чтобы избежать путаницы.)
Я мог бы ответить слишком поздно по поводу поста, однако мне удалось достичь этого, используя библиотеку привязки данных Android Android DataBinding Анкет Я создал пользовательскую привязку, чтобы убедиться, что слушатель не вызывается до тех пор, пока не будет изменен выбранный элемент, поэтому, даже если пользователь выбирает ту же позицию снова и снова событие, которое не будет запущено.
Макет XML -файл
<layout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Spinner
android:id="@+id/spinner"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:spinnerMode="dropdown"
android:layout_below="@id/member_img"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/member_btn"
android:padding="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:textColor="@color/colorAccent"
app:position="@{0}"
/>
</RelativeLayout>
</layout>
app:position
это где вы проходите позицию, чтобы быть выбранным.
Пользовательская привязка
@BindingAdapter(value={ "position"}, requireAll=false)
public static void setSpinnerAdapter(Spinner spinner, int selected)
{
final int [] selectedposition= new int[1];
selectedposition[0]=selected;
// custom adapter or you can set default adapter
CustomSpinnerAdapter customSpinnerAdapter = new CustomSpinnerAdapter(spinner.getContext(), <arraylist you want to add to spinner>);
spinner.setAdapter(customSpinnerAdapter);
spinner.setSelection(selected,false);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String item = parent.getItemAtPosition(position).toString();
if( position!=selectedposition[0]) {
selectedposition[0]=position;
// do your stuff here
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Вы можете прочитать больше о привязке пользовательских данных здесь Android Custom Setter
ПРИМЕЧАНИЕ
Не забудьте включить DataBinding в вашем файле Gradle
android { .... dataBinding { enabled = true } }
Включите свои файлы макета в
<layout>
теги
mYear.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View arg1, int item, long arg3) {
if (mYearSpinnerAdapter.isEnabled(item)) {
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});