2011-01-08 21 views
8

Sto facendo un po 'di lavoro AsyncTask dopo che l'utente fa clic su un elemento nel mio ListView. Mi piacerebbe disabilitare l'oggetto in modo che non possa essere cliccato due volte. Ho semplificato l'ascoltatore dei clic per contenere solo questo metodo, ma non fa ancora nulla per me, la vista sembra la stessa e si lascia di nuovo clicere di nuovo, con mio grande dispiacere.Visualizzazione figlio Android ListView setEnabled() e setClickable() non fare nulla

public void onItemClick(AdapterView<?> parent, View clickedView, 
    int position, long id) { 
    item = (Episode) parent.getItemAtPosition(position); 
    clickedView.setClickable(false); 
    clickedView.setEnabled(false); 
    clickedView.invalidate(); 
} 

My View per ogni riga è una consuetudine LinearLayout con due TextView s.

+0

tutti voi sono corretti. Ora funziona, grazie – Axarydax

risposta

20

Quindi, potresti utilizzare anche un adattatore personalizzato. Se lo fai, sovrascrivere questi metodi:

public boolean areAllItemsEnabled() { 
    return false; 
} 

public boolean isEnabled(int position) { 
    // return false if position == position you want to disable 
} 

Poi, quando si riceve un clic dire l'adattatore che cosa era l'ultimo elemento selezionato e restituire false su isEnabled per quella posizione. Ad esempio, puoi avere un metodo come questo nell'adattatore:

private int mLastClicked; 
public void setLastClicked(int lastClicked){ 
    mLastClicked = lastClicked; 
} 
+0

hi im avendo difficoltà a trovare la posizione dell'ultimo elemento cliccato mi puoi chiarire per questo grazie – NoobMe

5

Il tuo problema non è completamente chiaro. Sto interpretando la tua domanda come se ti aspettassi che onItemClick() non venga chiamato in base alle tue chiamate setEnabled() e setClickable().

Non sono sorpreso che non funziona, come onItemClick() è qualcosa che ListView fa, non la vista figlio. Prova a ignorare areAllItemsEnabled() e isEnabled() nel tuo ListAdapter.

4

Ci sono diversi motivi per cui il tuo approccio non funzionerà.

1) onItemClick viene chiamato solo a causa di eventi di tastiera. Specificamente KeyKevent.KEYCODE_ENTER. Non viene chiamato tramite alcun altro percorso di codice. Quindi, gestirlo è utile solo se si sta tentando di fornire supporto per tastiera/trackball.

codice sorgente di Android per i metodi rilevanti AbsListView:

public boolean onKeyUp(int keyCode, KeyEvent event) { 
    switch (keyCode) { 
    case KeyEvent.KEYCODE_DPAD_CENTER: 
    case KeyEvent.KEYCODE_ENTER: 
     if (!isEnabled()) { 
      return true; 
     } 
     if (isClickable() && isPressed() && 
       mSelectedPosition >= 0 && mAdapter != null && 
       mSelectedPosition < mAdapter.getCount()) { 

      final View view = getChildAt(mSelectedPosition - mFirstPosition); 
      if (view != null) { 
       performItemClick(view, mSelectedPosition, mSelectedRowId); 
       view.setPressed(false); 
      } 
      setPressed(false); 
      return true; 
     } 
     break; 
    } 
    return super.onKeyUp(keyCode, event); 
} 

public boolean performItemClick(View view, int position, long id) { 
    if (mOnItemClickListener != null) { 
     playSoundEffect(SoundEffectConstants.CLICK); 
     mOnItemClickListener.onItemClick(this, view, position, id); 
     return true; 
    } 

    return false; 
} 

2) Si sta impostando le informazioni cliccabile direttamente sulla vista. Le visualizzazioni visualizzate tramite qualsiasi AdapterView sono eteree. Vengono creati su richiesta dello AdapterView e esistono solo finché il AdapterView ne ha bisogno. Non dovresti impostare alcun dato su di essi che desideri conservare. È possibile chiamare setEnabled e setClickable su di essi per ottenere l'effetto immediato, ma se si desidera che tali informazioni persistano è necessario memorizzarle in un punto che l'Adapter abbia accesso in modo che possa essere ricreato quando lo AdapterView ricrea la View per quella posizione.

3) È necessario gestire l'evento onClick per l'effettivo View che viene fatto clic. Dove gestisci questo dipende da te. Il posto migliore è probabilmente il tuo Adapter che poi può o non può passarlo al tuo Activity a seconda di quali sono i tuoi requisiti di progettazione. È qui che devi gestire i tuoi eventi touch.

Vedi questo codice per una semplice attività:

public class PhoneTesting extends Activity { 
    private static final String TAG = "PhoneTesting"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     Log.d(TAG, "onCreate()"); 

     List<String> strings = new ArrayList<String>(); 
     for(int i = 0 ; i < 20 ; i++) { 
      strings.add(Integer.toString(i)); 
     } 

     ListView list = (ListView) this.findViewById(R.id.list); 

     list.setAdapter(new SimpleAdapter(this, 0, 0, strings)); 
     list.setOnItemClickListener(new OnItemClickListener() { 

      @Override 
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
       Log.d(TAG, "onItemClick: " + id); 
      } 
     }); 

    } 

    class SimpleAdapter extends ArrayAdapter<String> implements OnClickListener { 
     SimpleAdapter(Context context, int resource, int textViewResourceId, List<String> objects) { 
      super(context, resource, textViewResourceId, objects); 
     } 

     SimpleAdapter(Context context, int resource, int textViewResourceId, String[] objects) { 
      super(context, resource, textViewResourceId, objects); 
     } 

     SimpleAdapter(Context context, int resource, int textViewResourceId) { 
      super(context, resource, textViewResourceId); 
     } 

     SimpleAdapter(Context context, int textViewResourceId, List<String> objects) { 
      super(context, textViewResourceId, objects); 
     } 

     SimpleAdapter(Context context, int textViewResourceId, String[] objects) { 
      super(context, textViewResourceId, objects); 
     } 

     SimpleAdapter(Context context, int textViewResourceId) { 
      super(context, textViewResourceId); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      TextView b = position % 2 == 0 ? new Button(this.getContext()) : new TextView(this.getContext()); 
      b.setText(this.getItem(position)); 

      b.setOnClickListener(this); 

      return b; 
     } 

     @Override 
     public void onClick(View v) { 
      TextView t = (TextView) v; 
      Log.d(TAG, "onClick: " + t.getText()); 
     } 

     @Override 
     public boolean isEnabled(int position) { 
      return position % 2 == 0 ? false : true; 
     } 

    } 
} 

Se si esegue questo codice e fare clic su uno qualsiasi dei View s nel ListView si noterà nell'output logcat che solo onClick viene chiamato. onItemClick non viene mai chiamato.

Si noti inoltre che isEnabled nell'adattatore non sembra avere effetto se lo View è selezionabile o meno. Non sono sicuro di come interpretarlo. Tuttavia, ciò significa che se si desidera controllare la proprietà di Adapter, è necessario impostare Adapter quando viene creato lo strumento View e in qualche modo conservare tali informazioni.

+0

Avrei anche bisogno di sovrascrivere 'areAllItemsEnabled()' nell'adattatore, ma grazie – Axarydax

+0

Sì, dimenticato di quello. ancora onItemClick viene chiamato solo tramite eventi della tastiera. – Qberticus

18

se si desidera la disattivazione voce di clic nella visualizzazione elenco uso clickedView.setClickable(true);

+8

Sembra molto sbagliato, ma per qualche ragione funziona. Strano, forse un professionista può illuminarci perché setClickable (true) avrà effettivamente l'effetto desiderato di rendere la vista non cliccabile. – Bachi

+0

Scoperto la stessa cosa. È strano ma funziona. – Drejc

+1

indead! Sembra un bug nel sistema. – user717572

Problemi correlati