- Forum-Beiträge: 38
07.05.2014, 15:33:35 via Website
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 ?
Empfohlener redaktioneller Inhalt
Mit Deiner Zustimmung wird hier ein externer Inhalt geladen.
Mit Klick auf den oben stehenden Button erklärst Du Dich damit einverstanden, dass Dir externe Inhalte angezeigt werden dürfen. Dabei können personenbezogene Daten an Drittanbieter übermittelt werden. Mehr Infos dazu findest Du in unserer Datenschutzerklärung.