Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/220.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用微调器从自定义listview中删除了错误的行_Android_Listview_Android Listview_Adapter_Android Adapter - Fatal编程技术网

Android 使用微调器从自定义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包含两个微调器(学生姓名和成绩)、设

我正在开发一个包含自定义ListView的应用程序,该应用程序带有一个删除按钮,我可以从主活动中更新该按钮

从ListView中删除一行时遇到问题,尽管我正在从自定义列表视图中删除正确的索引并调用
notifyDataChanged()
方法,但GUI无法正确更新

在这里,我写了一个示例项目,就像我在idea中的真实项目一样,只是更多示例:

  • 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);
    }
}
活动\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;
}
}