Android Advertencia: Ventana ya enfocada, ignorando la ganancia de enfoque
Necesito tus ojos, chicos. He luchado con mi código durante mucho tiempo, y todavía me quedo atrapado como un estante viejo.
Verá, hay numerosos temas relacionados con la advertencia de Android:
- Alternativa a la CLASE SPINNER ALTAMENTE FLAWED en Android
- Android: Rellenar Spinner del código Java mediante programación
- Android Appcompat v21 - utilizar el estilo antiguo del hilandero
- Spinner Dropdown CheckedTextView Autoscroll
- Android- ¿Cómo utilizar Spinner en un AlertDialog?
W/InputMethodManagerService: Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub...
He leído un montón de ellos, no encontró nada útil y mis ojos están cansados.
Estoy trabajando en un componente spinner, cuyo primer elemento, llamado como Add new … dispara un cuadro de diálogo para agregar otro elemento a la lista. Debido a que actualmente tengo dos spinners (en una actividad), he creado una clase wrapper para los spinners, que se encarga de la lógica y he creado la clase, que se extiende DialogFragment
ya que ambos hilanderos dispara un diálogo similar con <EditText>
, sólo Diferentes títulos.
Pero desde el punto de vista, sólo funciona el primer spinner. El segundo hilandero, cuando choosig opción a Agregar nuevo … , no hace nada, sólo producir advertencia escrita anteriormente.
Spinner envoltura
Es la clase interna de KegAddActivity extends AppCompatActivity
y se ve así:
public class ExtendableSpinner implements AdapterView.OnItemSelectedListener, View.OnTouchListener { private static final int ADD_NEW_ID = -1; private final Spinner _mSpinner; private final String _mTableName; private final int _mAddNewTitle; private final MatrixCursor _mAddOptionsCursor; private Uri _mAdapterUri; private SimpleCursorAdapter _mAdapter; private boolean _mWasTouched; public ExtendableSpinner(Spinner spinner, String tableName, int addNewTitle) { super(); _mSpinner = spinner; _mTableName = tableName; _mAdapterUri = BeerBookUriHandler.getUri(tableName); _mAddNewTitle = addNewTitle; _mAddOptionsCursor = new MatrixCursor(new String[]{Table.COL_ID, BeerTable.COL_NAME}); _mAddOptionsCursor.addRow(new String[]{"" + ADD_NEW_ID, getString(addNewTitle) + '\u2026'}); _mSpinner.setOnTouchListener(this); _mSpinner.setOnItemSelectedListener(this); } public void setAdapterUri(Uri uri) { _mAdapterUri = uri; } @Override public boolean onTouch(View v, MotionEvent event) { _mWasTouched = true; return false; } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (_mWasTouched) { // event fired by user if (id == ADD_NEW_ID) { Bundle args = new Bundle(); args.putInt(AddNewDialogFragment.TITLE, _mAddNewTitle); _mAddNewDialogFragment = new AddNewDialogFragment(); _mAddNewDialogFragment.setArguments(args); _mAddNewDialogFragment.show(getSupportFragmentManager(), _mTableName + "AddNewDialog"); } } else { // event fired at activity start int selection = 0; if (_mAdapter.getCount() > 1) { selection = 1; Uri uri = BeerBookUriHandler.getUri(KegTable.NAME + "/last"); Cursor cursor = getContentResolver().query(uri, new String[]{ _mTableName + "." + Table.COL_ID }, null, null, null); if (cursor != null && cursor.moveToFirst()) { long lastUsedId = cursor.getLong(0); selection = getPositionForId(lastUsedId); } cursor.close(); } _mSpinner.setSelection(selection); } } @Override public void onNothingSelected(AdapterView<?> parent) { } public void populate() { Cursor cursor = getContentResolver().query(_mAdapterUri, BEER_PROJECTION, null, null, BeerTable.COL_NAME); Cursor extendedCursor = new MergeCursor(new Cursor[]{ _mAddOptionsCursor, cursor}); _mAdapter = new SimpleCursorAdapter(getApplicationContext(), SPINNER_LAYOUT, extendedCursor, new String[] { BeerTable.COL_NAME }, new int[] {android.R.id.text1}, 0); _mAdapter.setDropDownViewResource(SPINNER_ITEM_LAYOUT); _mSpinner.setAdapter(_mAdapter); } public int getPositionForId(long itemId) { int pos = 0; for(int i = 1, l = _mAdapter.getCount(); i < l; i++) if (itemId == _mAdapter.getItemId(i)) { pos = i; break; } return pos; } public long getSelectedId() { return _mSpinner.getSelectedItemId(); } public void setSelectionById(long id) { _mSpinner.setSelection(getPositionForId(id)); } }
KegAddActivity
En el método onCreate()
I instanciar hilanderos así
protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... final Spinner beerSpinner = (Spinner) findViewById(R.id.keg_add_beer); _mBeerSpinner = new ExtendableSpinner(beerSpinner, BeerTable.NAME, R.string.beer_add); // initially disable, wait for brewery selection beerSpinner.setEnabled(false); final Spinner brewerySpinner = (Spinner) findViewById(R.id.keg_add_brewery); _mBrewerySpinner = new ExtendableSpinner(brewerySpinner, BreweryTable.NAME, R.string.brewery_add) { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { super.onItemSelected(parent, view, position, id); if (id > 0) { // brewery selected, populate beerSpinner Uri uri = BeerBookUriHandler.getUri(BreweryTable.NAME + "/" + getSelectedId() + "/" + BeerTable.NAME); _mBeerSpinner.setAdapterUri(uri); _mBeerSpinner.populate(); beerSpinner.setEnabled(true); } } }; _mBrewerySpinner.populate(); ... }
Mi actual sospecha
Debido a que el primer hilandero funciona y el segundo no, y son bastante similares, creo que los hilanderos concurrentes para el enfoque de alguna manera, pero realmente no lo sé. He intentado reemplazar DialogFragment
con Actividades separadas dedicadas a cada spinner y evento onItemSelected
de spinners entonces llamado startActivityForResult()
pero esto causó el mismo problema, el primer spinner funcionó bien y el segundo falló con la advertencia, por lo que el problema podría estar en código De hilanderos.
¡Finalmente algún progreso!
Por suerte, encontré la constelación donde funciona y luego fue capaz de averiguar por qué no.
Si el elemento de Agregar nuevo … está seleccionado actualmente en el hilandero y, a continuación, seleccione Agregar nuevo … , vuelva a producir ignoring focus gain
advertencia de ignoring focus gain
. Pero si selecciona algún otro elemento en la hiladora y luego selecciona Agregar nuevo … , funciona. El problema era, si no hay otros elementos en la hiladora, no puede realizar dicha reselección. Parece que el evento onItemSelected
no se propaga, si selecciona una opción ya seleccionada. Pero esto es un problema importante, ya que el usuario puede pulsar Cancelar en AddNewDialog
para volver a la vista principal y, a continuación, el Agregar nuevo … permanecerá seleccionado y podría ser la única opción, por lo que no hay forma de abrir AddNewDialog
nuevo.
La solución, como hacerlo funcionar, es agregar otro elemento predeterminado, como Elegir de la lista … y si el usuario cancela el cuadro de diálogo, vuelva a seleccionar la opción de hiladora a la opción predeterminada. Lo probaré y mantendré este mensaje actualizado.
Conclusión
Si selecciona en el Spinner
un elemento previamente seleccionado, el evento itemSelected
no se propagará y W/InputMethodManagerService: Window already focused, ignoring focus gain
advertencia de W/InputMethodManagerService: Window already focused, ignoring focus gain
aparece en su registro.
Dado que Spinner
no soporta el evento onItemClick
, la única solución que encontré trabajando es definir una opción predeterminada Elija de la lista … y si el usuario cancela AddNewDialog
el detector onDialogNegativeClick
restablece el hilador al valor predeterminado Elija desde … el elemento, On Add new … hay cambio en la selección y el evento se propaga.
- Tengo un error: setOnItemClickListener no se puede utilizar con un spinner, ¿qué está mal?
- ¿Cómo establecer el valor predeterminado en el menú desplegable de hilandero en Android?
- Android-spinnerwheel - Pestaña individual dibujable
- Android Spinner - ¿cómo hacer el tamaño del elemento seleccionado actualmente?
- Cómo cambiar el tamaño del texto del elemento Android Spinner
- Android.R.simple_spinner_adapter no se puede resolver
- Android - ¿Cómo añadir un borde inferior (enfocado) a spinner?
- Valores de conjunto de spinner de Android
Encontramos el mismo problema y determinamos que la única manera alrededor de esto era crear un Spinner de encargo que llama a onItemSelected()
incluso si el mismo artículo fue seleccionado:
public class CustomSpinner extends Spinner { public CustomSpinner(Context contextArg){ super(contextArg); } public CustomSpinner(Context contextArg, AttributeSet attributeSetArg){ super(contextArg, attributeSetArg); } public CustomSpinner(Context contextArg, AttributeSet attributeSetArg, int styleArg){ super(contextArg, attributeSetArg, styleArg); } @Override public void setSelection(int positionArg){ boolean samePosition = positionArg == getSelectedItemPosition(); super.setSelection(positionArg, false); // here we modifiy the Spinner's default behavior if(samePosition){ // we dispatch the event, even if the position is the same OnItemSelectedListener onItemSelectedListener = getOnItemSelectedListener(); if(onItemSelectedListener != null){ onItemSelectedListener.onItemSelected(this, getSelectedView(), positionArg, getSelectedItemId()); } } } @Override public void setSelection(int positionArg, boolean animateArg){ boolean samePosition = positionArg == getSelectedItemPosition(); super.setSelection(positionArg, animateArg); // here we modifiy the Spinner's default behavior if(samePosition){ // we dispatch the event, even if the position is the same OnItemSelectedListener onItemSelectedListener = getOnItemSelectedListener(); if(onItemSelectedListener != null){ onItemSelectedListener.onItemSelected(this, getSelectedView(), positionArg, getSelectedItemId()); } } } }
- Localización fusionada Api setSmallestDisplacement ignorado / no funciona
- Vista web de Android con geolocalización de HTML 5