Как сделать так, чтобы onItemSelected не запускался при создании нового экземпляра Spinner?

StackOverflow https://stackoverflow.com/questions/2562248

Вопрос

Я думал о нескольких не слишком элегантных способах решения этой проблемы, но я знаю, что, должно быть, чего-то не хватает.

Мой 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 () для обнаружения активности пользователя,

ссылка : https://stackoverflow.com/a/25070696/4772917

У меня есть Выполнено с самым простым способом:

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

ПРИМЕЧАНИЕ

  1. Не забудьте включить DataBinding в вашем файле Gradle

       android {
     ....
     dataBinding {
     enabled = true
    }
    }
    
  2. Включите свои файлы макета в <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) {
            }
        });
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top