我正在开发一个应用程序,它包含一个自定义列表视图,带有一个删除按钮,我可以从主活动中更新该按钮。
从ListView中删除一行时遇到问题,尽管我正在从自定义列表视图中删除正确的索引,并调用notifyDataChanged()
方法,但GUI无法正确更新。
在这里,我写了一个示例项目,就像我在idea中的真实项目,只是更多示例:
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;
}
}
我的问题是图形用户界面没有正确更新,图形用户界面上被删除的项目仍然出现在屏幕上,如下所示:
有人能告诉我如何从GUI中删除正确的行吗?
编辑
编辑
如果有人想尝试,我添加学生类和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>
基本上,这个问题是由于视图回收而发生的。将这两个方法添加到适配器类中
@Override
public int getViewTypeCount() {
return studentID.size() + 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
下面的链接解释了为什么要添加这两种方法。通过列表视图检查动态生成的复选框时出现问题
我希望有帮助!
我建议您在列表视图中使用setOnItemClickListener方法。有一些优点:
OnClickListener
onItemClick(AdapterView
然后,您可以使用该位置从适配器中移除项目。
问题在于
holder.spNames.setTag(position);
和
holder.spNames.setSelection((Integer) holder.spNames.getTag());
在“onItemSelected()”中为name设置标记时。当你删除该项目时,你会从学生列表中删除该项目,但是标签呢。
假设您在0处删除了该项目。
现在,当调用“notifyDataSetChanged()”时,它将根据可用的数据重新填充listview。现在,在这里
else{
holder = (ViewHolder) view.getTag();
}
正在被调用。当getView()中的i=0时,您将获得前一个填充列表的第0个索引的视图。因此,“(整数)holder.spNames.get标签()”将指向前一个标签(即前一个列表的0)。这可能是问题的原因。
我正在发布更新的代码
listviewAdapter
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;
}
}
我通过SDK成功地创建了一个自定义度量,但无法删除它我无法从web控制台找到删除它的选项(从SDK中也无法找到删除/取消它的方法) 它创建了一个名为“MyCompany/MyResources”的度量,但我无法删除它
我对下面的Java程序有问题。我在Ubuntu系统上使用带有JDK-1.8u25的JavaFX。我想显示一个ListView,并从列表中删除突出显示的条目。我创建了一个列表,并将其与一个可观察列表配对,以通知侦听器事件。然而,通过删除下面的“orderOvList.remove(i,i 1)”项来更改列表似乎会生成另一个侦听器事件。所以,我似乎在侦听器代码的主体中递归。我想过将list元素从nor
我很难从自定义对象的ArrayList中删除重复项。 删除重复项 自定义对象等于() 删除重复项后的输出 关于为什么它实际上没有删除重复项,有什么提示吗?或者它实际上是通过将副本替换为原始副本来删除副本?不知道这里发生了什么。
我有一个JTable,其中添加了一个JButton(Delete button)和一个JComboBox作为两列上的自定义单元格编辑器。现在,当我在组合框中选择一个项目并单击Delete按钮时,所选行被删除,但已删除行的组合框在该行上呈现。我是否也必须从表中删除单元编辑器。如果我不选择我的组合框,代码就可以正常工作。请帮帮我。 我的代码是这样的:- 我在main中实例化了我的类的一个对象,然后单击
我已经在TestCase下创建了一些属性列表。例如,看下面的截图。 我试图通过以下groovy脚本teststep删除Testcase_Property属性: 当我重新加载项目时,当我单击测试用例名称时,Testcase_Property属性仍然存在于Custom Properties选项卡中。 谢谢 卡鲁纳加拉·潘迪
我使用下面的布局实现了一个加载微调器图标: 但这使用默认的Android微调器。我想用我从preloaders.net得到的加载图标来替换微调器,如下所示: 如何用此自定义微调器替换默认的Android微调器?