ListView-Elemente per Update/Delete bearbeiten

  • Antworten:2
Wicki12
  • Forum-Beiträge: 38

07.05.2014, 15:33:35 via Website

Hallo,

Ich habe eine ListView und möchte deren Einträge per Update und Delete bearbeiten. Das Update funktioniert, aber beim Delete erhalte zuweilen Fehler "05-07 13:33:58.956: E/AndroidRuntime(14560): java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2" in der Methode onFocusChange.
Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.listvieweditable"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroidCustomListViewActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
        <Button
        android:id="@+id/delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Delete" />

    <ListView android:id="@+id/MyList" android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        >
    </ListView>
</LinearLayout>

Code:

package com.example.listvieweditable;   
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class AndroidCustomListViewActivity extends Activity implements OnClickListener {
  private ListView myList;
  private MyAdapter myAdapter;
  Button bdel;
  int delPos=-1;
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    myList = (ListView) findViewById(R.id.MyList);
    myList.setItemsCanFocus(true);
    myAdapter = new MyAdapter();
    myList.setAdapter(myAdapter);
    bdel = (Button)findViewById(R.id.delete);
    bdel.setOnClickListener(this);
  }
    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        String s=myAdapter.myItems.get(delPos).caption;
        Toast.makeText(this,"delPos:"+delPos+","+s, Toast.LENGTH_LONG).show();
        if (delPos>=0 && delPos < myAdapter.myItems.size()) {
        myAdapter.myItems.remove(delPos);
        myAdapter.notifyDataSetChanged();
        }
    }

  public class MyAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    public ArrayList<ListItem> myItems = new ArrayList<ListItem>();
    public MyAdapter() {
      mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      for (int i = 0; i < 3; i++) {
          ListItem listItem = new ListItem();
          listItem.caption = "Caption" + i;
          myItems.add(listItem);
      }
      notifyDataSetChanged();
    }
    public int getCount() {
        return myItems.size();
    }
        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub
            Log.d("****** ","getItem == null");
            return null;
        }
        public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      //Par.: position in ListView,LinearLayout for a List-row, ListView
      ViewHolder holder;
      if (convertView == null) {
          holder = new ViewHolder();
          convertView = mInflater.inflate(R.layout.item, null);
          holder.caption = (EditText) convertView
                  .findViewById(R.id.ItemCaption);
          Log.d("****** ","convertView == null");
          convertView.setTag(holder);
      } else {
          holder = (ViewHolder) convertView.getTag();
          Log.d("****** ",holder.caption.getText().toString());
      }
      //Fill EditText with the value you have in data source
      //myItems enthält ListItem-Instanzen
      ListItem li=(ListItem) (myItems.get(position));  //******** hier trat der Fehler auf
      holder.caption.setText( li.caption);
      holder.caption.setId(position);
      //we need to update adapter once we finish with editing
      holder.caption.setOnFocusChangeListener(new OnFocusChangeListener() {
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus){
              delPos=v.getId();
            } else {
              final int position = v.getId();
              final EditText caption = (EditText) v;
              String s=caption.getText().toString();
              if (s.charAt(0)=='-' && myItems.size()>0 && (delPos>=0 && delPos<myItems.size())) {
                myItems.remove(position);
                myAdapter.notifyDataSetChanged();
                Toast.makeText(getApplicationContext(),"delPos:"+delPos+","+myItems.size(), Toast.LENGTH_LONG).show();
                delPos=-1;
                return;
              }
              ListItem li=(ListItem)(myItems.get(position));
              li.caption=caption.getText().toString();
            }
        }
      });

      return convertView;
    }

  }

  class ViewHolder {
      EditText caption;
  }
  class ListItem {
      String caption;
  }
}

Ich habe 2 Varianten in dem Code:
Variante 1:
Button wird nicht benutzt, in einem Eintrag wird das 1. Zeichen auf - gesetzt, das soll dann zum Delete des Eintrags führen. Auf diese Variante bezieht sich der Fehler, es sollte der letzte Eintrag gelöscht werden.
Variante 2:
Ein Klick auf den Button soll den Eintrag, der den Fokus hat, löschen.
Beide Varianten sind nicht fehlerfrei. Anscheinend stimmt die Synchronisation zwischen ListView und Adapter nicht trotz Verwendung von notifyDataSetChanged.

Wo liegt der Fehler ?
Gibt es eine andere Lösung ?

Antworten
impjor
  • Forum-Beiträge: 1.793

07.05.2014, 20:44:47 via App

Kann es sein, dass du in delPos die Id der View speicherst und dann versuchst das delPoste-te Element zu entfernen?
Du musst in delPos die position der View speichern. (Also das wievielte Element die View ist)

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Wicki12
  • Forum-Beiträge: 38

08.05.2014, 08:39:44 via Website

Vielen Dank ! Das war's, manchmal sieht man den Wald vor lauter Bäumen nicht.
Habe noch eine Zusatzfrage:
Wenn ich nach einem Klick in das EditText-Feld dieses editieren will, dann erscheint zunächst das Soft-Keyboard. Um allerdings nun was eingeben zu können muss ich noch 3-mal kurz einen Touch im Feld machen ehe der Eingabe-Cursor erscheint. Woran liegt das und wie kann ich erreichen, dass ich nach dem 1. Touch auch sofort etwas eingeben kann ?

Gruß Wicki

— geändert am 08.05.2014, 11:23:40

Antworten