如何从列表中(随机地)删除项目并维护 ListView
How to remove items (randomly) from a list and maintaining the ListView
有一个 ListView 显示 Arraylist 的项目,这些项目由用户动态添加(通过 EditText 和确认按钮)。在 Listview 的每个项目中,都有一个 remove ImageView,它从 List 中删除相应的项目(因此从 ListView 中删除)。
目标是使 ListView 上的删除按钮 (ImageView) 正常工作。
目前我正在为每个项目添加一个 onClickListener,当它们被添加到列表中时。 onClickListener 执行一个方法,该方法使用 list.remove(int i) 函数,然后使用 notifyDataSetChanged() 更新 ListView。
[[主要 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>
如您所见,当将 onClickListener 添加到 ImageView 时,将根据列表中的当前项数(减 1)添加 itemid。
如果我们有 3 个项目:"i0"、"i1" 和 "i2" 和 "i1" 将被删除,"i2" 上带有 remove 方法的 onClickListener 具有旧索引。 "i2"ArrayList 中的索引已自动减少,但 remove-function 参数保持不变。
如何解决这个问题?
谢谢:)
(我希望我没有删除任何必要的代码,因为我试图只留下重要的部分)
可以通过覆盖标准适配器的 getView() 来访问 ListView 项目内的视图。试试这个 [使用 setTag() 和 getTag()]:
arrayAdapter = new ArrayAdapter(this, R.layout.listview_item, R.id.listView_item_text, list){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = super.getView(position, convertView, parent);
ImageView removeImage = itemView.findViewById(R.id.ImageView_removeItem);
removeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (int)v.getTag();
Log.d("Logging","itemId: " + pos);
remove(pos);
notifyDataSetChanged();
}
});
removeImage.setTag(position);
return itemView;
}
};
希望对您有所帮助!
另一个答案[使用final]:
arrayAdapter = new ArrayAdapter(this, R.layout.listview_item, R.id.listView_item_text, list){
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View itemView = super.getView(position, convertView, parent);
ImageView removeImage = itemView.findViewById(R.id.ImageView_removeItem);
removeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//int pos = (int)v.getTag();
Log.d("Logging","itemId: " + position);
remove(position);
notifyDataSetChanged();
}
});
//removeImage.setTag(position);
return itemView;
}
};
有一个 ListView 显示 Arraylist 的项目,这些项目由用户动态添加(通过 EditText 和确认按钮)。在 Listview 的每个项目中,都有一个 remove ImageView,它从 List 中删除相应的项目(因此从 ListView 中删除)。
目标是使 ListView 上的删除按钮 (ImageView) 正常工作。
目前我正在为每个项目添加一个 onClickListener,当它们被添加到列表中时。 onClickListener 执行一个方法,该方法使用 list.remove(int i) 函数,然后使用 notifyDataSetChanged() 更新 ListView。
[[主要 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>
如您所见,当将 onClickListener 添加到 ImageView 时,将根据列表中的当前项数(减 1)添加 itemid。 如果我们有 3 个项目:"i0"、"i1" 和 "i2" 和 "i1" 将被删除,"i2" 上带有 remove 方法的 onClickListener 具有旧索引。 "i2"ArrayList 中的索引已自动减少,但 remove-function 参数保持不变。
如何解决这个问题?
谢谢:)
(我希望我没有删除任何必要的代码,因为我试图只留下重要的部分)
可以通过覆盖标准适配器的 getView() 来访问 ListView 项目内的视图。试试这个 [使用 setTag() 和 getTag()]:
arrayAdapter = new ArrayAdapter(this, R.layout.listview_item, R.id.listView_item_text, list){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = super.getView(position, convertView, parent);
ImageView removeImage = itemView.findViewById(R.id.ImageView_removeItem);
removeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (int)v.getTag();
Log.d("Logging","itemId: " + pos);
remove(pos);
notifyDataSetChanged();
}
});
removeImage.setTag(position);
return itemView;
}
};
希望对您有所帮助!
另一个答案[使用final]:
arrayAdapter = new ArrayAdapter(this, R.layout.listview_item, R.id.listView_item_text, list){
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View itemView = super.getView(position, convertView, parent);
ImageView removeImage = itemView.findViewById(R.id.ImageView_removeItem);
removeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//int pos = (int)v.getTag();
Log.d("Logging","itemId: " + position);
remove(position);
notifyDataSetChanged();
}
});
//removeImage.setTag(position);
return itemView;
}
};