2012-04-12 11 views
0

Ich entwickle eine App, in der ich eine ListView brauche, deren Zeilen eine TextView, 2 CheckBox und einen Spinner haben.Wie man Spinner in ListView Arbeit in Android bekommen?

Ich habe jedoch Probleme mit onItemSelected() des Spinner, wie es jedes Mal aufgerufen wird, wenn es für jede Zeile angezeigt wird. Bei dieser Methode aktualisiere ich Datenbankeinträge mit der gewählten Option, aber wie Android es automatisch aufruft, jedes Mal, wenn die Elemente zurückgesetzt werden, weil Android sie mit der Position 0 aufruft, wird dieser Wert in der Datenbank aktualisiert.

Ich habe eine Menge Links über das Problem mit onItemSelected() und einige Hacks gelesen, aber alle von ihnen sind ohne eine ListView zu verwenden. Irgendwelche Punkte hier?

Ich habe versucht, in einer Liste zu verfolgen, welche Positionen tatsächlich angezeigt werden, damit es funktioniert, aber es nicht funktioniert. Ich denke, es ist wegen des Recyclings in Android, dass die Fehlerbehebungsmethode für Spinner bereits aufgerufen!

Also der Punkt ist: Wie kann ich einen echten Anruf zu onItemSelected() aufgrund einer Benutzerauswahl aus dem Android-Aufruf unterscheiden, wenn der Spinner angezeigt wird?

Hier ist der Code meines Adapters, der SimpleCursorAdapter erweitert.

Vielen Dank im Voraus.

public ParticipationAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { 
    super(context, layout, c, from, to); 
    mActivity = (Activity)context; 
    ParticipationComment.ParticipationCommentManager commentManager = new ParticipationComment.ParticipationCommentManager(mActivity); 
    mParticipationCommentsCursor = commentManager.get(); 
    mActivity.startManagingCursor(mParticipationCommentsCursor); 
    commentManager.detach(); 
    mPositionsOfCursorIds = getPositionsOfCursorIds(mParticipationCommentsCursor); 
    mSpinnerPositionsDisplayed = new ArrayList<Integer>(); 
} 

@Override 
public View getView(final int participationPosition, View convertView, ViewGroup parent) { 
    final Cursor participationsCursor = getCursor(); 
    mActivity.startManagingCursor(participationsCursor); 
    participationsCursor.moveToPosition(participationPosition); 
    View participationRow; 
    if (convertView == null) { 
     participationRow = LayoutInflater.from(mActivity).inflate(R.layout.participation_row_student, null); 
    } else { 
     mSpinnerPositionsDisplayed.remove((Integer)convertView.getTag()); 
     participationRow = convertView; 
    } 
    participationRow.setTag(participationPosition); 
    Spinner commentSpinner = (Spinner)participationRow.findViewById(R.id.participation_comment_id_spinner); 
    SimpleCursorAdapter commentSpinnerAdapter = new SimpleCursorAdapter(
      mActivity, 
      android.R.layout.simple_spinner_item, 
      mParticipationCommentsCursor, 
      new String[] {DatabaseManager.NAME}, 
      new int[] {android.R.id.text1} 
    ); 
    commentSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    commentSpinner.setAdapter(commentSpinnerAdapter); 
    long participationCommentId = participationsCursor.getLong(participationsCursor.getColumnIndex(DatabaseManager.PARTICIPATION_COMMENT_ID)); 
    if (participationCommentId != 0) { 
     commentSpinner.setSelection(mPositionsOfCursorIds.get(participationCommentId)); 
    } 
    commentSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { 
     @Override 
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
      participationsCursor.moveToPosition(participationPosition); 
      if (!mSpinnerPositionsDisplayed.contains(participationPosition)) { 
       // Android calls this method the first time a Spinner is displayed, 
       // to differentiate from a real user click we check if the current Spinner's position 
       // in the ListView is being shown 
       mSpinnerPositionsDisplayed.add(participationPosition); 
      } else { 
       ParticipationComment participationComment = new ParticipationComment((Cursor)parent.getItemAtPosition(position)); 
       Participation.ParticipationManager participationManager = new Participation.ParticipationManager(mActivity); 
       Participation participation = new Participation(participationsCursor); 
       participation.setConnectionProfileParticipationCommentId(participationComment.getConnectionProfileId()); 
       participation.setParticipationCommentId(participationComment.getIdOpenErp()); 
       participation.setChanged(true); 
       participationManager.update(participation); 
       participationManager.detach(); 
      } 
     } 

     @Override 
     public void onNothingSelected(AdapterView<?> parent) { 
      // Not used 
     } 
    }); 
    TextView studentName = (TextView)participationRow.findViewById(R.id.participation_student_name); 
    studentName.setText(participationsCursor.getString(participationsCursor.getColumnIndex(DatabaseManager.NAME))); 
    CheckBox expectedPresent = (CheckBox)participationRow.findViewById(R.id.participation_expected_present_value); 
    expectedPresent.setChecked(participationsCursor.getInt(participationsCursor.getColumnIndex(DatabaseManager.EXPECTED_PRESENT)) == 1); 
    CheckBox present = (CheckBox)participationRow.findViewById(R.id.participation_present_value); 
    present.setChecked(participationsCursor.getInt(participationsCursor.getColumnIndex(DatabaseManager.PRESENT)) == 1); 
    return participationRow; 
} 

Antwort

3

Ein besserer Weg ist es, eine Variante zu verwenden Alertdialog .. wie this .. und eine Schaltfläche erstellen, die zunächst die erste Auswahl als Text hat und seine auf der Grundlage des Alertdialog Wahl geändert ..

+0

Vielen Dank für Ihre Antwort! Morgen werde ich es versuchen und dir etwas sagen! Aber ich werde 'public AlertDialog.Builder setCursor (Cursorcursor, DialogInterface.OnClickListener listener, String labelColumn)' stattdessen verwenden, weil ich die Ursprungsdaten in einer db-Tabelle habe. Ich denke, dass ich mit diesem Ansatz in der Lage sein werde, dem Benutzer zu erlauben, keine der Möglichkeiten auszuwählen, die ich tatsächlich benötige und die mit dem Spinner nicht möglich ist. – Caumons

+0

@Caumons .. viel Glück .. – ngesh

+0

Vielen Dank, so sehr! Ich habe schließlich die Auswahl innerhalb der ListView mit Schaltflächen und alertDialogs wie Sie vorgeschlagen implementiert. Das funktioniert großartig! Ich habe im Dialog die Methode 'setSingleChoiceItems()' verwendet, da Sie damit eine Standardauswahl definieren können. Ich habe Ihre Antwort aufgefrischt und akzeptiert, um Ihnen +25 Wiederholungen zu geben! :) – Caumons

2

Wie wäre es mit einem kleinen Flag, um den ersten Aufruf von ItemSelected zu verwerfen?

+0

Wo und wie kann ich mach das? Ich habe keine Ideen ... :(Ich habe bereits eine Liste mit den angezeigten Positionen im Auge ... Wenn also die aktuelle Position nicht vorhanden ist und "onItemSelected()" aufgerufen wird, dann wird es von Android gemacht, sonst Es ist ein Benutzer klicken, aber ... Es scheint, dass Android erinnert, wenn bereits angezeigt wird und das tut mir weh! Ich denke, das ist wegen der Recycling-Muster mit Android (convertView) – Caumons

+0

Ich denke, dass Sie Ihren Zähler jedes Mal zurücksetzen sollten Eine Ansicht wird erstellt oder recycelt (Methode getView Ihres Adapters). Behalten Sie einen Zähler für jede Sicht, setzen Sie ihn zurück, wenn die Sicht von der Methode getView gestellt wird. Verwerfen Sie die ersten Ereignisse jeder Sicht. – Snicolas

+0

Ich denke, dass dieser Ansatz mein Ziel erreichen wird Hände, weil ich nicht genau weiß, wie das Recycling umgesetzt wird und wo ich den Zähler zurücksetzen sollte. Ich werde die andere Lösung von @sandy versuchen, die viel einfacher scheint. Ich denke immer, dass Google Jungs dieses unerwünschte Verhalten der Methode verbessern sollten. .. Danke dir Ou sowieso! :) – Caumons