Cómo abrir una ruleta con un solo clic cuando otra ruleta está abierta

Tengo pocos spinners en un formulario. Cuando hago clic en cualquiera de ellos se abre y muestra las opciones. Cuando hago clic en cualquier otro spinner que cierra el spinner abierto, pero luego tengo que hacer clic de nuevo en el spinner deseado para abrirlo.

Quisiera coger el primer tecleo en el hilandero 2to de modo que pueda cerrar el primer hilandero abierto y después abrir el hilandero chascado.

Vi mensajes sobre el cierre de la ruleta en cualquier clic fuera, pero eso no es suficiente porque todavía no sé que el hilador deseado se ha hecho clic (el onclick() de la segunda ruleta no se disparó).

Estoy un poco ocupado para escribir y darte algún código, pero al obtener ayuda de enlaces como éste puedes obtener un fragmento. Así que aquí está mi idea. En primer lugar al crear su vista, busque la coordenada de los hilanderos, por ejemplo, la hiladora A, B y C. Escriba también una función (por ejemplo foo(...) ) que devuelve la coordenada del punto pulsado pero no la consume . A continuación, registre A, B y C onItemSelectedListeners y en su cheque onNothingSelected si el punto seleccionado está en otras dos áreas de spinners o no (usando foo(...) que escribió anteriormente). De esta manera usted puede conseguir lo que quiere. Lo siento estoy ocupado y perezoso, pero esto funciona. Espero haberlo ayudado.

Actualización (para recibir los toques):

Bueno, he intentado varios enfoques, para ser honesto ninguno de ellos funcionó, incluso haciendo actividad interceptar eventos táctiles no ayudó, así que supongo que el caso con spinner abierto es como pop ups, en ese caso una solución viene a mi mente.

Usted necesita poner una capa transparente encima de todas sus vistas para interceptar el tacto, pero debe ser como qué se utiliza en la pantalla de la cerradura de modo que ningún otro diálogo o visión pueda estar encima de eso. Si ha escrito una aplicación de pantalla de bloqueo o ha intentado hacerlo, sabe cómo hacerlo.

Sin embargo, para tal caso el permiso será excesivo y no te sugiero que lo hagas a menos que encuentres otra forma pacífica.

Pruebe este código de una línea para abrir su hiladora sin hacer clic en él

  ((Spinner) findViewById(R.id.selected_area_spinner)).performClick(); 

Pero utilice este código después de inicializar su hiladora

Prueba este código para ayudarte

 import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; /** * Created by riyazudinp on 8/11/2016. */ public class MyActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, View.OnClickListener { private String dataForSpinnerOne[] = {"A", "B", "C", "D", "E"}; private String dataForSpinnerTwo[] = {"F", "G", "H", "I", "J"}; private String dataForSpinnerThree[] = {"K", "L", "M", "N", "O"}; private Spinner spinnerOne; private Spinner spinnerTwo; private Spinner spinnerThree; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); spinnerOne = (Spinner) findViewById(R.id.spinner1); spinnerTwo = (Spinner) findViewById(R.id.spinner2); spinnerThree = (Spinner) findViewById(R.id.spinner3); ArrayAdapter<String> adapter1 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerOne); ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerTwo); ArrayAdapter<String> adapter3 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerThree); spinnerOne.setAdapter(adapter1); spinnerTwo.setAdapter(adapter2); spinnerThree.setAdapter(adapter3); spinnerOne.setOnItemSelectedListener(this); spinnerTwo.setOnItemSelectedListener(this); spinnerThree.setOnItemSelectedListener(this); spinnerOne.setOnClickListener(this); spinnerTwo.setOnClickListener(this); spinnerThree.setOnClickListener(this); } @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { if (view == spinnerOne) { //Spinner One Clicked //add your code when spinner iten selected } if (view == spinnerTwo) { //Spinner Two Clicked //add your code when spinner iten selected } if (view == spinnerThree) { //Spinner Three Clicked //add your code when spinner iten selected } } @Override public void onNothingSelected(AdapterView<?> adapterView) { } @Override public void onClick(View view) { if (view == spinnerOne) { spinnerOne.performClick(); spinnerTwo.performClick(); spinnerThree.performClick(); } if (view == spinnerTwo) { spinnerOne.performClick(); spinnerTwo.performClick(); spinnerThree.performClick(); } if (view == spinnerThree) { spinnerOne.performClick(); spinnerTwo.performClick(); spinnerThree.performClick(); } } } 

AnotherSpinner.setSelection (open_item_index);

Esto es casi imposible.

Jerarquía de la clase Spinner

 Spinner -> AbsSpinner -> AdapterView<SpinnerAdapter> -> ViewGroup -> View 

De Spinner.Java

 /** * <p>A spinner does not support item click events. Calling this method * will raise an exception.</p> * <p>Instead use {@link AdapterView#setOnItemSelectedListener}. * * @param l this listener will be ignored */ 

No tenemos acceso al evento de clic .

 OnClickListener uses public interface DialogInterface. 

Lo mejor que puedo sugerir es usar un menú emergente en lugar de un Spinner si esta "característica" te fastidia.

@Zvi @Erfan Mowlaei no parece publicar ningún código. Aquí está mi idea de su idea:

  ViewTreeObserver vto1 = spinnerOne.getViewTreeObserver(); vto1.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if( !spinnerOne.getViewTreeObserver().isAlive() ) { Log.e(TAG,"OnGlobalLayoutListener: ***NOT alive***"); // only need to calculate once, so remove listener // viewToMeasure.getViewTreeObserver().removeGlobalOnLayoutListener(this); }else { Log.e(TAG,"OnGlobalLayoutListener: ***alive***"); /*when you post a message to a View, the messages will only be delivered after the View has been fully initialized (including being measured)*/ spinnerOne .post(new Runnable() { @Override public void run() { Log.e(TAG,"OnGlobalLayoutListener: ***run test***"); // safe to get height and width here spinnerTwo.setSelected(false); spinnerThree.setSelected(false); spinnerOne.performClick(); // LayerDrawable ld = (LayerDrawable)spinnerOne.getBackground();//cast problem // ld.setLayerInset(1, 0, spinnerOne.getHeight() / 2, 0, 0); } }); } } }); 

Nota: Como he dicho, ninguno de estos métodos puede funcionar, ya que los eventos se generan y consumen en la biblioteca de tiempo de ejecución. Ellos NUNCA están expuestos.

Otras cosas que no funcionan:

 spinnerOne.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if(hasFocus) { spinnerOne.performClick(); Log.v(TAG, "onFocusChange spinnerOne GOT the focus"); Toast.makeText(getApplicationContext(), "spinnerOne got the focus", Toast.LENGTH_SHORT).show(); }else { Log.v(TAG, "onFocusChange spinnerOne LOST the focus"); Toast.makeText(getApplicationContext(), "spinnerOne lost the focus", Toast.LENGTH_SHORT).show(); } } }); 

Una nueva esperanza Episodio IV?

Su problema plantea una entrada en logcat cada vez que realiza la "maniobra Zvi":

 08-14 01:19:55.575: W/InputEventReceiver(8676): Attempted to finish an input event but the input event receiver has already been disposed. 

No tengo mucha esperanza en resolver el problema.

Aquí está un hilandero personalizado que hace exactamente lo que necesita,

PopUpActionspinner Github

PopupActionSpinner.java

  package com.selva.widget; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ListPopupWindow; import android.widget.PopupWindow; import android.widget.Spinner; import java.lang.reflect.Field; import java.lang.reflect.Method; public class PopupActionSpinner extends Spinner { private static final String M_POPUP = "mPopup"; private static final String DROPDOWN_POPUP = "DropdownPopup"; private static final String IS_SHOWING = "isShowing"; private static final String DIALOG_POPUP = "DialogPopup"; private static final int MODE_UNKNOWN = -1; private PopupTouchInterceptor popupTouchInterceptor; private Field mFieldSpinnerPopup = null; private PopupActionSpinner[] mPopupActionSpinnersArr = null; /** * Construct a new spinner with the given context's theme and the supplied attribute set. * * @param context The Context the view is running in, through which it can * access the current theme, resources, etc. * @param attrs The attributes of the XML tag that is inflating the view. */ public PopupActionSpinner(Context context, AttributeSet attrs) { super(context, attrs); } /** * Define your own Interface to control what happens when the Spinner dropdown popup is open. * @param mpopupTouchInterceptor */ public void setPopupTouchInterceptor(PopupTouchInterceptor mpopupTouchInterceptor, PopupActionSpinner[] allSpinners ) { this.popupTouchInterceptor = mpopupTouchInterceptor; this.mPopupActionSpinnersArr = allSpinners; } @Override public boolean performClick() { boolean handled = true; try { handled = super.performClick(); // reflecting Spinner.mPopup field if (isFieldSpinnerPopupNull()) { mFieldSpinnerPopup = this.getClass().getSuperclass().getDeclaredField(M_POPUP); } // disable access checks to Spinner.mPopup mFieldSpinnerPopup.setAccessible(true); // get value of mPopup field Object spinnerPopup = mFieldSpinnerPopup.get(this); // reflecting SpinnerPopup.isShowing() Method isShowing = mFieldSpinnerPopup.getType() .getDeclaredMethod(IS_SHOWING, (Class[]) null); // calling Spinner.mPopup.isShowing() boolean isShowingResult = (boolean) isShowing.invoke(spinnerPopup, (Object[]) null); if (isShowingResult) { // check if mFieldSpinnerPopup is a dialog popup if (getSpinnerMode() == MODE_DIALOG) { //Do Nothing } else if (getSpinnerMode() == MODE_DROPDOWN) { // reflecting Spinner.mPopup.mPopup Field fieldPopupWindow = ListPopupWindow.class.getDeclaredField(M_POPUP); fieldPopupWindow.setAccessible(true); ((PopupWindow) fieldPopupWindow.get(spinnerPopup)).setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { if(!isViewInBounds(view,event.getRawX(),event.getRawY())) { for (View spinnerView : mPopupActionSpinnersArr) if (isPointInsideView(event.getRawX(), event.getRawY(), spinnerView)) { popupTouchInterceptor.onTouchIntercepted(spinnerView); break; } } break; } } return false; } }); fieldPopupWindow.setAccessible(false); } } // enable access checks to Spinner.mPopup mFieldSpinnerPopup.setAccessible(false); } catch (Exception exception) { } return handled; } public static boolean isPointInsideView(float x, float y, View view){ int location[] = new int[2]; view.getLocationOnScreen(location); int viewX = location[0]; int viewY = location[1]; //point is inside view bounds if(( x > viewX && x < (viewX + view.getWidth())) && ( y > viewY && y < (viewY + view.getHeight()))){ return true; } else { return false; } } private boolean isViewInBounds(View view, float x, float y) { Rect outRect = new Rect(); int[] location = new int[2]; view.getDrawingRect(outRect); view.getLocationOnScreen(location); outRect.offset(location[0], location[1]); return outRect.contains((int)x, (int)y); } /** * Returns a constant describing how the user selects choices from the spinner. * * @return the choosing mode of this <code>{@link Spinner}</code> */ public int getSpinnerMode() { int result = MODE_UNKNOWN; try { // reflecting Spinner.mPopup field if (isFieldSpinnerPopupNull()) { mFieldSpinnerPopup = this.getClass().getSuperclass().getDeclaredField(M_POPUP); } // get Spinner.DropdownPopup class name mFieldSpinnerPopup.setAccessible(true); String spinnerPopupClassName = mFieldSpinnerPopup.get(this).getClass().getSimpleName(); mFieldSpinnerPopup.setAccessible(false); switch (spinnerPopupClassName) { case DIALOG_POPUP: result = MODE_DIALOG; break; case DROPDOWN_POPUP: result = MODE_DROPDOWN; break; default: } } catch (Exception exception) { exception.printStackTrace(); } return result; } public boolean isFieldSpinnerPopupNull() { return mFieldSpinnerPopup == null; } @Override public int getId() { return super.getId(); } } 

He utilizado Java Reflection para acceder a la ventana emergente y sobreescribir el TouchInteceptor. De esta manera, podrás controlar el evento táctil en tu actividad y, a su vez, podrás abrir el siguiente hilandero sin tener que hacer clic dos veces.

Para obtener una idea clara, clonar mi muestra de Github y ejecutar el mismo. Por favor, hágamelo saber si tiene alguna duda.

  • Tamaño del texto del hilandero Android
  • Alternativa a la CLASE SPINNER ALTAMENTE FLAWED en Android
  • Spinner: onItemSelected no se llama cuando el elemento seleccionado permanece igual
  • El girador se desplaza hacia arriba cuando está encendidoPulse o desplaza lentamente
  • Implementación de eventos Spinner with Butter Knife
  • Androide spinner evento de incendio cuando la misma selección de artículo se hace
  • ¿Por qué mi hilandero personalizado está llenando el nombre de mi paquete?
  • Tema predeterminado de Spinner a EditarTexto android
  • Ajuste del valor de la hiladora dinámicamente
  • Cómo hacer una fecha spinner en Android
  • Android.database.sqlite.SQLiteCursor@435b9ba0
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.