Я работаю над приложением, которое содержит настраиваемый ListView с кнопкой удаления, которую я обновляю из основного действия.
У меня проблема с удалением строки из ListView, хотя я удаляю правильный индекс из пользовательского представления списка и вызываю notifyDataChanged()
method, графический интерфейс не обновляется правильно.
Здесь я написал образец проекта, похожий на мой настоящий в идее, просто еще образец:
- activity_main.xml (основной макет) содержит ListView только с именем listview.
- listview_row.xml содержит два счетчика (имя и оценка учащегося), кнопку установки и удаления и текстовое представление.
- Студенческий класс содержит две переменные: имя (String) и оценку (int).
MainActivity.java:
public class MainActivity extends Activity {
ListView listView;
listviewAdapter adapter;
ArrayList<Student> students = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] names = new String[]{"Tom", "Ben", "Gil", "Adam", "Moshe", "Adi", "Michael", "Yasmin", "Jessica", "Caroline", "Avi", "Yael"};
students.add(new Student());
students.add(new Student());
students.add(new Student());
adapter = new listviewAdapter(this, students, names);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
public void updateStatus(int position)
{
View convertView = listView.getChildAt(position - listView.getFirstVisiblePosition());
TextView tvValue = (TextView) convertView.findViewById(R.id.tv_Value);
Spinner spName = (Spinner) convertView.findViewById(R.id.spNames);
Spinner spGrade = (Spinner) convertView.findViewById(R.id.spGrades);
tvValue.setText(spName.getSelectedItem().toString() + " got " + spGrade.getSelectedItem().toString());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_Add)
{
students.add(new Student());
adapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
}
listviewAdapter.java
public class listviewAdapter extends BaseAdapter
{
public Activity context;
public LayoutInflater inflater;
private ArrayList<Student> studentID;
private String[] studentsNames;
public listviewAdapter(Activity context, ArrayList<Student> students, String[] names)
{
super();
studentID = students;
studentsNames = names;
this.context = context;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return studentID.size();
}
@Override
public Object getItem(int position) {
return studentID.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return studentID.size() + 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
public class ViewHolder {
Spinner spNames, spGrades;
TextView tvValue;
Button btnSet, btnRemove;
}
@Override
public View getView(int i, View view, final ViewGroup viewGroup)
{
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_row, null);
holder.spNames = (Spinner) view.findViewById(R.id.spNames);
holder.spGrades = (Spinner) view.findViewById(R.id.spGrades);
holder.tvValue = (TextView) view.findViewById(R.id.tv_Value);
holder.btnSet = (Button) view.findViewById(R.id.btn_setValue);
holder.btnRemove = (Button) view.findViewById(R.id.btn_Remove);
view.setTag(holder);
holder.spNames.setTag(0);
holder.spGrades.setTag(0);
}
else{
holder = (ViewHolder) view.getTag();
}
// pop spinner names
ArrayAdapter<String> studentsNamesAdapater = new ArrayAdapter<>
(view.getContext(), android.R.layout.simple_spinner_dropdown_item, studentsNames);
studentsNamesAdapater.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spNames.setAdapter(studentsNamesAdapater);
// pop spinner grades
String[] grades = new String[101];
for (int grade = 0; grade < 101; grade++)
grades[grade] = String.valueOf(grade);
final ArrayAdapter<String> studentsGradesAdapter = new ArrayAdapter<>
(view.getContext(), android.R.layout.simple_spinner_dropdown_item, grades);
studentsGradesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spGrades.setAdapter(studentsGradesAdapter);
// select the right spNames index
holder.spNames.setSelection((Integer) holder.spNames.getTag());
// saving spinner index
holder.spNames.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
holder.spNames.setTag(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// select the right spGrades index
holder.spGrades.setSelection((Integer) holder.spGrades.getTag());
// saving spinner index
holder.spGrades.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
holder.spGrades.setTag(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// set (variable and textview)
holder.btnSet.setTag(i);
holder.btnSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// update studentID
int position = (Integer) v.getTag();
Student tmp = new Student(holder.spNames.getSelectedItem().toString(), Integer.valueOf(holder.spGrades.getSelectedItem().toString()));
studentID.set(position, tmp);
((MainActivity) context).updateStatus(position);
}
});
// remove row
holder.btnRemove.setTag(i);
holder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (Integer) v.getTag();
studentID.remove(position);
//notifyDataSetChanged();
((MainActivity) context).adapter.notifyDataSetChanged();
// for debug
String dStatus = "Vector size: " + studentID.size() + "\n";
for (int index = 0; index < studentID.size(); index++)
dStatus += studentID.get(index).name + " " + studentID.get(index).grade + "\n";
Toast.makeText(v.getContext(), dStatus, Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
Моя проблема в том, что графический интерфейс не обновляется правильно, удаленный элемент графического интерфейса все еще отображается на экране, как вы можете видеть ниже:
Может кто-нибудь посоветовать мне, пожалуйста, как удалить правую строку также из графического интерфейса?
ИЗМЕНИТЬ
- Я обновляю свой адаптер listview и использую теги, когда вы мне отвечаете, не работает.
- Я также обнаружил странную проблему, когда пытаюсь добавить в Student после удаления одного. По какой-то причине он «запоминает» последнего студента и возвращает его с полными данными, как вы можете видеть на картинке обновления.
РЕДАКТИРОВАТЬ2
Если кто-то хочет попробовать, я добавляю класс Student и источники XML:
Student.java
public class Student
{
public String name;
public int grade;
public Student()
{
name = "";
grade = 0;
}
public Student(String _name, int _grade)
{
name = _name;
grade = _grade;
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"
android:layout_gravity="center_horizontal"
android:dividerHeight="2dp" />
</LinearLayout>
listview_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#c4e0ff">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/spNames" />
<Spinner
android:layout_width="100dp"
android:layout_height="wrap_content"
android:id="@+id/spGrades"
android:layout_marginLeft="10dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Set Value"
android:id="@+id/btn_setValue" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="@+id/tv_Value" />
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remove"
android:id="@+id/btn_Remove"
android:layout_marginLeft="30dp" />
</LinearLayout>
</LinearLayout>