2015-04-25 4 views
16

Sto provando a usare una tastiera per navigare attraverso una GridView di elementi.Navigazione da tastiera con Android GridView non scorre la griglia

Nella demo breve, che contiene solo una GridView (contenente le visualizzazioni delle voci con android:focusable="true"), è possibile notare che nessuno degli elementi ottiene focus: la griglia è la cosa che scorre (gli elementi non diventano arancione).

scrolling short demo

Aggiunta del android:descendantFocusability="afterDescendants" permette ogni elemento da mettere a fuoco in primo luogo, ma ancora, non continua a scorrere il GridView modo da poter navigare verso il basso:

with descendent focusability set

Facendo clic su un elemento (con il mouse o premendo Invio se l'oggetto è stato messo a fuoco, dopo la correzione della messa a fuoco discendente) trasforma un oggetto in blu, indicando che è in stato premuto.

clicking grid items

@ layout/activity_my.xml:

<?xml version="1.0" encoding="utf-8"?> 
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/listview" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:numColumns="2" /> 

@ layout/dummy_item.xml:

<?xml version="1.0" encoding="utf-8"?> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/dummy_item_parent" 
    android:layout_width="match_parent" 
    android:layout_height="150dp" 
    android:gravity="center" 
    android:focusable="true" 
    android:clickable="true" 
    android:background="@drawable/item_background" /> 

@ drawable/item_background.xml:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" /> 
    <item android:state_focused="true" android:drawable="@android:color/holo_orange_light" /> 
    <item android:drawable="@android:color/holo_red_light" /> 
</selector> 

MyA ctivity.java (con ListAdapter):

public class MyActivity extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_my); 

     AbsListView listview = (AbsListView) findViewById(R.id.listview); 
     listview.setAdapter(new DummyAdapter(getLayoutInflater())); 
    } 

    private static class DummyAdapter extends BaseAdapter { 

     private static final int COUNT = 25; 

     private final LayoutInflater layoutInflater; 

     DummyAdapter(LayoutInflater layoutInflater) { 
      this.layoutInflater = layoutInflater; 
     } 

     @Override 
     public int getCount() { 
      return COUNT; 
     } 

     @Override 
     public String getItem(int position) { 
      return "Item " + position; 
     } 

     @Override 
     public long getItemId(int position) { 
      return position; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      View view = convertView; 
      if (view == null) { 
       view = layoutInflater.inflate(R.layout.dummy_item, parent, false); 
      } 
      ((TextView) view).setText(getItem(position)); 
      return view; 
     } 

    } 

} 

Swapping GridView per un controllo ListView, senza cambiare l'adattatore, o la vista voce/vista elementi attributi, si comporterà come previsto - gli elementi possono essere focalizzati e ListView sarà scorrere verso il basso, in modo che tutti gli oggetti possano essere focalizzati usando solo l'input da tastiera. Inoltre, l'utilizzo di RecyclerView con LinearLayoutManager/GridLayoutManager funzionerà correttamente.

Ho provato questo su API 16 e 22 con gli stessi risultati. Ho provato le impostazioni dell'attributo android:descendantFocusability su GridView a afterDescendents con lo stesso risultato.

+0

I userebbe un RecyclerView con GridLayoutManager (e un ItemDecoration, che tenga conto campate voce, per la spaziatura articolo) per implementare tale schermo. Questa domanda è solo per curiosità! – ataulm

+0

Hai provato 'android: drawSelectorOnTop =" true "'? – Manu

+0

@manu grazie per la risposta. Il problema non è con il selettore/focus, è con non essere in grado di scorrere (puoi vedere nella seconda gif, sono in grado di vedere il selettore, ma non riesco ancora a scorrere). – ataulm

risposta

1

Ho provato il codice e non funziona con GridView, come hai detto, ma ho qualche problema anche con ListView. Lo ListView scorre correttamente, ma viene evidenziato solo il primo elemento di ogni pagina.

Con queste piccole modifiche è possibile ottenere l'effetto desiderato su GridView e ListView.

Rimuovere android:descendantFocusability in activity_my.xml:

<?xml version="1.0" encoding="utf-8"?> 
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/listview" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:numColumns="2" /> 

Rimuovere android:focusable in dummy_item.xml:

<?xml version="1.0" encoding="utf-8"?> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/dummy_item_parent" 
    android:layout_width="match_parent" 
    android:layout_height="150dp" 
    android:gravity="center" 
    android:clickable="true" 
    android:background="@drawable/item_background" /> 

Change android:state_focused-android:state_selected in item_background.xml:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" /> 
    <item android:state_selected="true" android:drawable="@android:color/holo_orange_light" /> 
    <item android:drawable="@android:color/holo_red_light" /> 
</selector> 
+0

lo stato selezionato è diverso dallo stato focalizzato però - considera anche il caso in cui vuoi rappresentare gli elementi che sono effettivamente selezionati, per esempio in modalità multi selezione: avrai anche bisogno di avere gli stati 'selected',' focused' e 'selected + focused' per essere accessibili. – ataulm

+0

questo evidenzia che GridView è solo spazzatura - non dovrebbe selezionare elementi ('view.setSelected (true)') mentre ci si sposta attraverso la griglia, ma questa è una buona soluzione (usando lo stato selezionato) - potrebbe fare affidamento su 'state_checked' per quando in realtà vuoi selezionare un elemento, implementando Checkable su ItemView e' view.setChecked (true) 'dove si farebbe setSelected. Grazie! – ataulm

+0

un ultimo commento - Ho sbagliato - 'selected' è lo stesso, concettualmente, come' focalizzato' - nel codice sorgente, loro (Google) si scusano persino per la denominazione! 'setActivated (boolean)' è quello che ho immaginato sarebbe 'setSelected (boolean)'. – ataulm