Android 使用微调器从自定义listview中删除了错误的行
我正在开发一个包含自定义ListView的应用程序,该应用程序带有一个删除按钮,我可以从主活动中更新该按钮 从ListView中删除一行时遇到问题,尽管我正在从自定义列表视图中删除正确的索引并调用Android 使用微调器从自定义listview中删除了错误的行,android,listview,android-listview,adapter,android-adapter,Android,Listview,Android Listview,Adapter,Android Adapter,我正在开发一个包含自定义ListView的应用程序,该应用程序带有一个删除按钮,我可以从主活动中更新该按钮 从ListView中删除一行时遇到问题,尽管我正在从自定义列表视图中删除正确的索引并调用notifyDataChanged()方法,但GUI无法正确更新 在这里,我写了一个示例项目,就像我在idea中的真实项目一样,只是更多示例: activity_main.xml(主布局)仅包含名为ListView的ListView listview_row.xml包含两个微调器(学生姓名和成绩)、设
notifyDataChanged()
方法,但GUI无法正确更新
在这里,我写了一个示例项目,就像我在idea中的真实项目一样,只是更多示例:
- activity_main.xml(主布局)仅包含名为ListView的ListView
- listview_row.xml包含两个微调器(学生姓名和成绩)、设置和删除按钮以及文本视图
- 学生类包含两个变量:名称(String)和年级(int)
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);
}
}
活动\u main.xml
listview_row.xml
每次创建按钮时,您需要将标记设置为位置,然后在单击内获取标记,它将返回正确的位置 在getView中
holder.btnRemove = (Button) view.findViewById(R.id.btn_Remove);
holder.btnRemove.setTag(position);
然后单击(视图)
然后尝试从位置移除该项目
更改:
@Override
public View getView(int final position, 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(viewHolder);
}
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> studentsGradesAdapater = new ArrayAdapter<>
(view.getContext(), android.R.layout.simple_spinner_dropdown_item, grades);
studentsGradesAdapater.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spGrades.setAdapter(studentsGradesAdapater);
// set (variable and textview)
holder.btnSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// update studentID
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.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
studentID.remove(position);
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;
}
@覆盖
公共视图getView(内部最终位置、视图视图、最终视图组视图组)
{
最终持票人;
如果(视图==null){
holder=新的ViewHolder();
视图=充气机。充气(R.layout.listview_行,空);
holder.spNames=(微调器)view.findViewById(R.id.spNames);
holder.spGrades=(微调器)view.findViewById(R.id.spGrades);
holder.tvValue=(TextView)view.findViewById(R.id.tv_值);
holder.btnSet=(按钮)view.findViewById(R.id.btn_setValue);
holder.btnRemove=(按钮)view.findViewById(R.id.btn\u Remove);
view.setTag(viewHolder);
}
否则{
holder=(ViewHolder)view.getTag();
}
//弹出微调器名称
ArrayAdapter StudentsNameAdapter=新的ArrayAdapter
(view.getContext(),android.R.layout.simple\u微调器\u下拉菜单\u项,studentsNames);
StudentsNameAdapter.setDropDownViewResource(android.R.layout.simple\u微调器\u下拉菜单\u项);
holder.spNames.setAdapter(StudentsNamesAdapter);
//波普纺纱机等级
字符串[]等级=新字符串[101];
对于(整数等级=0;等级<101;等级++)
等级[等级]=字符串.valueOf(等级);
最终阵列自适应学生GRADESADAPATER=新阵列自适应
(view.getContext(),android.R.layout.simple\u微调器\u下拉菜单\u项,等级);
studentsGradesAdapater.setDropDownViewResource(android.R.layout.simple\u spinner\u dropdown\u项目);
支架.spGrades.setAdapter(学生等级适配器);
//设置(变量和文本视图)
holder.btnSet.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
//更新学生ID
学生tmp=新学生(holder.spNames.getSelectedItem().toString(),Integer.valueOf(holder.spGrades.getSelectedItem().toString());
学生ID设置(位置,tmp);
((MainActivity)上下文)。updateStatus(位置);
}
});
//删除行
holder.btnRemove.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v)
{
学生ID。移除(位置);
notifyDataSetChanged();
//用于调试
字符串dStatus=“向量大小:”+studentID.size()+“\n”;
对于(int index=0;index
只需单击获取要删除的项目的位置,然后使用arraylist将其从arraylist中删除。删除(位置),然后调用notifyDataSetChanged 基本上,这个问题的发生是因为视图回收。将这两个方法添加到适配器类中
@Override
public int getViewTypeCount() {
return studentID.size() + 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
下面是一个链接,它解释了为什么必须添加这两种方法。
我希望有帮助 我建议您在列表视图中使用方法。有一些优点:
- 每次呈现项目时,您不必创建新的
OnClickListener
- 您可以直接访问视图的位置和视图本身:
onItemClick(AdapterView父项、视图、int位置、长id)
然后,您可以使用该位置从适配器中删除您的项目。如果您正在操作,请查看下面的代码
@Override
public View getView(int i, View view, final ViewGroup viewGroup)
{
if (view == null){
view == LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.xxx, null);
ViewHolder holder = new ViewHolder();
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);
}else{
holde = view.getTag();
}
/** You have to redefine each view every time because it can be recycled by the listview **/
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);
/** so no **//
/** you can set the position to the button as a tag **/
holder.btnRemove.setTag(i);
/** you MUST set the button OnClickListener after the view holder is created. you MUST NOT set the listener inside the if (view==null) pattern. **/
holder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
int position = (Integer)v.getTag(); //Get the position which you would like you remove from the button.
studentID.remove(position);
notifyDataSetChanged();
}
});
}
@覆盖
公共视图getView(int i、视图视图、最终视图组视图组)
{
如果(视图==null){
view==LayoutInflater.from(viewGroup.getContext()).flate(R.layout.xxx,null);
ViewHolder=新的ViewHolder();
holder.spNames=(微调器)view.findViewById(R.id.spNames);
holder.spGrades=(微调器)view.findViewById(R.id.spGrades);
holder.tvValue=(TextView)view.findViewById(R.id.tv_值);
holder.btnSet=(按钮)view.findViewById(R.id.btn_setValue);
holder.btnRemove=(按钮)view.findViewById(R.id.btn\u Remove);
视图.设置标签(支架);
}否则{
holde=view.getTag();
}
/**你必须重新付款
holder.btnRemove = (Button) view.findViewById(R.id.btn_Remove);
holder.btnRemove.setTag(position);
int position = (Integer) ((Button) view).getTag();
//remove item from position, and do the stuff here
@Override
public View getView(int final position, 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(viewHolder);
}
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> studentsGradesAdapater = new ArrayAdapter<>
(view.getContext(), android.R.layout.simple_spinner_dropdown_item, grades);
studentsGradesAdapater.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spGrades.setAdapter(studentsGradesAdapater);
// set (variable and textview)
holder.btnSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// update studentID
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.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
studentID.remove(position);
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;
}
@Override
public int getViewTypeCount() {
return studentID.size() + 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public View getView(int i, View view, final ViewGroup viewGroup)
{
if (view == null){
view == LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.xxx, null);
ViewHolder holder = new ViewHolder();
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);
}else{
holde = view.getTag();
}
/** You have to redefine each view every time because it can be recycled by the listview **/
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);
/** so no **//
/** you can set the position to the button as a tag **/
holder.btnRemove.setTag(i);
/** you MUST set the button OnClickListener after the view holder is created. you MUST NOT set the listener inside the if (view==null) pattern. **/
holder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
int position = (Integer)v.getTag(); //Get the position which you would like you remove from the button.
studentID.remove(position);
notifyDataSetChanged();
}
});
}
holder.spNames.setTag(position);
holder.spNames.setSelection((Integer) holder.spNames.getTag());
else{
holder = (ViewHolder) view.getTag();
}
public class ListviewAdapter extends BaseAdapter
{
public Activity context;
public LayoutInflater inflater;
private ArrayList<Student> studentID;
private String[] studentsNames;
private boolean isDeleted;
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 Student getItem(int position) {
return studentID.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public class ViewHolder {
Spinner spNames, spGrades;
TextView tvValue;
Button btnSet, btnRemove;
int index;
}
@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);
Log.e("IAM", "CALLED");
view.setTag(holder);
//holder.spNames.setTag(0);
//holder.spGrades.setTag(0);
}
else{
holder = (ViewHolder) view.getTag();
}
holder.index=i;
if(isDeleted){
holder.tvValue.setText(getItem(holder.index).getName()+ " got " + getItem(holder.index).getGrade());
}
// pop spinner names
ArrayAdapter<String> studentsNamesAdapater = new ArrayAdapter<String>
(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<String>
(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());
holder.spNames.setSelection(getItem(holder.index).getNameIndex());
// 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);
getItem(holder.index).setNameIndex(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// select the right spGrades index
// holder.spGrades.setSelection((Integer) holder.spGrades.getTag());
holder.spGrades.setSelection(getItem(holder.index).getGrageIndex());
// 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);
getItem(holder.index).setGrageIndex(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
//final int position = getRowPosition(v);
int position = (Integer) v.getTag();
// Student tmp = new Student(holder.spNames.getSelectedItem().toString(), Integer.valueOf(holder.spGrades.getSelectedItem().toString()));
// studentID.set(position, tmp);
getItem(position).setName(holder.spNames.getSelectedItem().toString());
getItem(position).setGrade(Integer.valueOf(holder.spGrades.getSelectedItem().toString()));
holder.tvValue.setText(getItem(position).getName()+ " got " + getItem(position).getGrade());
//((MainActivity) context).updateStatus(position);
}
});
// remove row
holder.btnRemove.setTag(i);
holder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//final int position = getRowPosition(v);
int position = (Integer) v.getTag();
studentID.remove(position);
notifyDataSetChanged();
//((MainActivity) context).adapter.notifyDataSetChanged();
isDeleted=true;
// 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;
}
public void printS() {
for (int i = 0; i <studentID.size(); i++) {
Log.e("NAME", ""+studentID.get(i).getName());
Log.e("GRADE", ""+studentID.get(i).getGrade());
}
}
}
public class Student {
public String name;
public int grade;
private int nameIndex;
private int grageIndex;
public Student()
{
name = "";
grade = 0;
}
public Student(String _name, int _grade)
{
name = _name;
grade = _grade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public int getNameIndex() {
return nameIndex;
}
public void setNameIndex(int nameIndex) {
this.nameIndex = nameIndex;
}
public int getGrageIndex() {
return grageIndex;
}
public void setGrageIndex(int grageIndex) {
this.grageIndex = grageIndex;
}
}