There is a ListView which displays the items of an Arraylist, which are dynamically added by the user (via an EditText and a confirm button). In each item of the Listview, there is a remove ImageView, which removes the respective item from the List (and hence from the ListView).
The goal is to make the remove button (ImageView) on the ListView work correctly.
Currently I am adding an onClickListener to each of the items, when they are added to the List. The onClickListener executes a method which uses the list.remove(int i) function and then notifyDataSetChanged() to update the ListView.
[[MAIN ACTIVITY]]
public class MainActivity extends AppCompatActivity {
// setting up member variables
ArrayList<String> list = new ArrayList<>();
ArrayAdapter<String> arrayAdapter;
TextInputLayout textInputLayout;
ListView listView;
Button addNewListItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
}
private void initialize() {
// binding listView, arrayadapter & button to the ones from the layout, setting up the array adapter
// Listview & adapted
listView = findViewById(R.id.listView_Items);
arrayAdapter = new ArrayAdapter<>(this, R.layout.listview_item, R.id.listView_item_text, list);
listView.setAdapter(arrayAdapter);
// buttons
addNewListItem = findViewById(R.id.button_addItem);
// setting up the onclick listener for addItem, de/increasePeople, calculate
addNewListItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addItem();
}
});
// setting up the onclick listener for the ok button in the soft keyboard for the
// edit text field when adding new items
textInputLayout = findViewById(R.id.TextInputLayout_itemToAdd);
textInputLayout.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
addItem();
return true;
}
return false;
}
});
}
private void addItem() {
textInputLayout = findViewById(R.id.TextInputLayout_itemToAdd);
String inputItem = textInputLayout.getEditText().getText().toString().trim();
// checking, if text was entered in the edit text and then adding it to the list
if (inputItem.isEmpty()) {
textInputLayout.setError("Can't be empty");
} else {
textInputLayout.setError(null);
list.add(inputItem);
// Adding an onClickListener to an item of the listview requires the listView to
// finish redrawing. OnLayoutChangeListener fires as soon as the listview has finished
// redrawing the listview.
// The layoutchangelistener is immediately removed and the onclicklistener is added.
listView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
listView.removeOnLayoutChangeListener(this);
// getting the child count of the listview to get the index of the item, that
// just has been added
int addedItemId = listView.getChildCount();
Toast.makeText(MainActivity.this,"addedItemid: " + addedItemId,Toast.LENGTH_SHORT).show();
View addedItemChildView = listView.getChildAt(addedItemId-1);
// initializing the imageview to which the onclicklistener has to be added
ImageView removeImage = addedItemChildView.findViewById(R.id.ImageView_removeItem);
// onclicklistener is an anonymous class and therefore requires
// the index to be final. initializing a final int with the index
final int itemId = addedItemId-1;
removeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Logging","itemId: " + itemId);
removeListItem(itemId);
}
});
}
});
arrayAdapter.notifyDataSetChanged();
}
}
private void removeListItem(int listItemId) {
list.remove(listItemId);
arrayAdapter.notifyDataSetChanged();
}
}
[[ACTIVITY_MAIN]]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/linearLayout_mainLayout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.TextInputLayout
android:id="@+id/TextInputLayout_itemToAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint_enterItem"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/button_addItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/button_addItem" />
<ListView
android:id="@+id/listView_Items"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
[[LISTVIEW_ITEM]]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp">
<ImageView
android:id="@+id/ImageView_removeItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="4"
android:clickable="true"
app:srcCompat="@android:drawable/ic_menu_delete" />
<TextView
android:id="@+id/listView_item_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_weight="2"
android:gravity="center_vertical"
tools:text="test" />
<android.support.design.widget.TextInputLayout
android:id="@+id/listView_item_edit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_weight="3"
android:gravity="center"
app:errorEnabled="false">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Value"
android:inputType="numberDecimal" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
As you can see, when the onClickListener is being added to the ImageView the itemid is added in accordance with the current amount of items in the list (minus 1). If we have 3 items: "i0", "i1" and "i2" and "i1" will be removed, the onClickListener with the remove method on "i2" has the old index. "i2"'s index has been automatically decreased in the ArrayList but the remove-function parameter remains the same.
How can this problem be solved?
Thank you :)
(i hope i didnt remove any essential code as i tried to leave only the important parts)