Listview 自定义过滤器在过滤列表中提供错误的点击项目
Listview custom filter gives wrong item on-clicked in filtered list
当我过滤我的列表并单击列表视图中的项目时,它提供了错误的项目信息。
假设我的列表包含 X、Y、Z。当我在列表中搜索以 Y 开头的东西时,我会得到 Y,但是当我单击 Y 时,它 returns 我是 X 或任何随机项目数据。
我的主要 activity:
public class exit_Activity extends AppCompatActivity {
String Show_url = "https://retrieve.php";
ListView removeView;
MyAdapter adapter;
public static ArrayList<Employee> employeeArrayList = new ArrayList<>();
Employee employee;
ProgressBar progressBar;
private SwipeRefreshLayout mSwipeRefreshLayout;
public static ArrayList<Employee> filterList = new ArrayList<>();
EditText search;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exit_);
retrieveData();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
///
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshlayout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.black, R.color.green, R.color.red);
mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.main_blue));
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mSwipeRefreshLayout.setRefreshing(true);
Toast.makeText(getApplicationContext(), "Updating..", Toast.LENGTH_SHORT).show();
retrieveData();
// do nothing
}
});
progressBar = (ProgressBar) findViewById(R.id.progressbar);
Sprite FoldingCube = new Wave();
progressBar.setIndeterminateDrawable(FoldingCube);
//time and date
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
exit_time();
removeView.requestLayout();
handler.postDelayed(this, 500);
}
}, 500);
//
//
//exit
removeView = findViewById(R.id.exit_entry);
adapter = new MyAdapter(this, employeeArrayList);
removeView.setAdapter(adapter);
//end
removeView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ProgressDialog progressDialog = new ProgressDialog(view.getContext());
startActivity(new Intent(getApplicationContext(), Edit_Activity.class)
.putExtra("id", id));
finish();
}
});
//searchView
search = findViewById(R.id.search);
search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
filterList.clear();
if (s.toString().isEmpty()) {
removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList));
adapter.notifyDataSetChanged();
} else {
Filter(s.toString());
}
}
});
//end
}
public void retrieveData() {
StringRequest request = new StringRequest(Request.Method.POST, Show_url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
employeeArrayList.clear();
try {
JSONObject jsonObject = new JSONObject(response);
String sucess = jsonObject.getString("success");
JSONArray jsonArray = jsonObject.getJSONArray("veeta_vehicles");
if (sucess.equals("1")) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String number = object.getString("number");
String name = object.getString("name");
String time = object.getString("surnam");
String date = object.getString("dob");
String time = object.getString("die");
String yes = object.getString("yes");
employee = new Employee(id, number, name, time, date, time, yes);
employeeArrayList.add(employee);
adapter.notifyDataSetChanged();
}
progressBar.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(getApplicationContext(), "List Updated", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(exit_Activity.this, error.getMessage(), Toast.LENGTH_LONG).show();
error.printStackTrace();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
adapter.notifyDataSetChanged();
}
MyAdapter.class:
public class MyAdapter extends ArrayAdapter<Employee> implements Filterable{
Context context;
List<Employee> arrayListEmployee;
public MyAdapter(@NonNull Context context, List<Employee> arrayListEmployee) {
super(context, R.layout.custom_list_item,arrayListEmployee);
this.context = context;
this.arrayListEmployee = arrayListEmployee;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_list_item,null,true);
TextView tvID = view.findViewById(R.id.txt_id);
TextView tvName = view.findViewById(R.id.view_vehicle_number);
tvID.setText(arrayListEmployee.get(position).getId());
tvName.setText(arrayListEmployee.get(position).getnumber());
return view;
}
@Override
public int getCount() {
return super.getCount();
}
请用简单的语言解释并提供我的解决方案。我是 android 工作室的新手。预先感谢 x1000
我发现方法有问题(查看评论):
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
//below every time you create new instance of MyAdapter - try comment this line (below) and test it
removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
//this is your first instance but you set new adapter for listView
adapter.notifyDataSetChanged();
}
并用这个替换你的方法:
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
adapter.clear()
adapter.addAll(filterList);
}
所以你不会每次都创建一个新的适配器实例,只是交换现有适配器的数据
我还没有测试过,但它应该可以与 OnItemClickListener 一起正常工作...
已编辑
同样的问题...
@Override
public void afterTextChanged(Editable s) {
filterList.clear();
if (s.toString().isEmpty()) {
//you set new instance of adapter and notify old, try comment this line (below) and test it
//removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList));
adapter.notifyDataSetChanged();
} else {
Filter(s.toString());
}
}
改成这个
@Override
public void afterTextChanged(Editable s) {
if (!s.toString().isEmpty()) {
filterList.clear(); //TODO here is problem, move this to your filter method
Filter(s.toString());
} else {
//Do nothing, if the EditText field is empty the list will remain filled
}
}
还有其他方法可以解决这个问题并进行改进,但我不想混淆你,因为 android 对你来说是新体验
已编辑
您正在使用 ArrayAdapter 但我认为它是 RecyclerView,忘记 swapData 方法并尝试新的更改...抱歉
adapter.clear()
adapter.addAll(filterList);
当我过滤我的列表并单击列表视图中的项目时,它提供了错误的项目信息。 假设我的列表包含 X、Y、Z。当我在列表中搜索以 Y 开头的东西时,我会得到 Y,但是当我单击 Y 时,它 returns 我是 X 或任何随机项目数据。 我的主要 activity:
public class exit_Activity extends AppCompatActivity {
String Show_url = "https://retrieve.php";
ListView removeView;
MyAdapter adapter;
public static ArrayList<Employee> employeeArrayList = new ArrayList<>();
Employee employee;
ProgressBar progressBar;
private SwipeRefreshLayout mSwipeRefreshLayout;
public static ArrayList<Employee> filterList = new ArrayList<>();
EditText search;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exit_);
retrieveData();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
///
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshlayout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.black, R.color.green, R.color.red);
mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.main_blue));
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mSwipeRefreshLayout.setRefreshing(true);
Toast.makeText(getApplicationContext(), "Updating..", Toast.LENGTH_SHORT).show();
retrieveData();
// do nothing
}
});
progressBar = (ProgressBar) findViewById(R.id.progressbar);
Sprite FoldingCube = new Wave();
progressBar.setIndeterminateDrawable(FoldingCube);
//time and date
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
exit_time();
removeView.requestLayout();
handler.postDelayed(this, 500);
}
}, 500);
//
//
//exit
removeView = findViewById(R.id.exit_entry);
adapter = new MyAdapter(this, employeeArrayList);
removeView.setAdapter(adapter);
//end
removeView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ProgressDialog progressDialog = new ProgressDialog(view.getContext());
startActivity(new Intent(getApplicationContext(), Edit_Activity.class)
.putExtra("id", id));
finish();
}
});
//searchView
search = findViewById(R.id.search);
search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
filterList.clear();
if (s.toString().isEmpty()) {
removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList));
adapter.notifyDataSetChanged();
} else {
Filter(s.toString());
}
}
});
//end
}
public void retrieveData() {
StringRequest request = new StringRequest(Request.Method.POST, Show_url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
employeeArrayList.clear();
try {
JSONObject jsonObject = new JSONObject(response);
String sucess = jsonObject.getString("success");
JSONArray jsonArray = jsonObject.getJSONArray("veeta_vehicles");
if (sucess.equals("1")) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String number = object.getString("number");
String name = object.getString("name");
String time = object.getString("surnam");
String date = object.getString("dob");
String time = object.getString("die");
String yes = object.getString("yes");
employee = new Employee(id, number, name, time, date, time, yes);
employeeArrayList.add(employee);
adapter.notifyDataSetChanged();
}
progressBar.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(getApplicationContext(), "List Updated", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(exit_Activity.this, error.getMessage(), Toast.LENGTH_LONG).show();
error.printStackTrace();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
adapter.notifyDataSetChanged();
}
MyAdapter.class:
public class MyAdapter extends ArrayAdapter<Employee> implements Filterable{
Context context;
List<Employee> arrayListEmployee;
public MyAdapter(@NonNull Context context, List<Employee> arrayListEmployee) {
super(context, R.layout.custom_list_item,arrayListEmployee);
this.context = context;
this.arrayListEmployee = arrayListEmployee;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_list_item,null,true);
TextView tvID = view.findViewById(R.id.txt_id);
TextView tvName = view.findViewById(R.id.view_vehicle_number);
tvID.setText(arrayListEmployee.get(position).getId());
tvName.setText(arrayListEmployee.get(position).getnumber());
return view;
}
@Override
public int getCount() {
return super.getCount();
}
请用简单的语言解释并提供我的解决方案。我是 android 工作室的新手。预先感谢 x1000
我发现方法有问题(查看评论):
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
//below every time you create new instance of MyAdapter - try comment this line (below) and test it
removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
//this is your first instance but you set new adapter for listView
adapter.notifyDataSetChanged();
}
并用这个替换你的方法:
private void Filter(String text) {
for (Employee post : employeeArrayList) {
String filterPattern = text.toLowerCase().trim();
if (post.getnumber().toLowerCase().contains(filterPattern)) {
filterList.add(post);
}
}
adapter.clear()
adapter.addAll(filterList);
}
所以你不会每次都创建一个新的适配器实例,只是交换现有适配器的数据
我还没有测试过,但它应该可以与 OnItemClickListener 一起正常工作...
已编辑
同样的问题...
@Override
public void afterTextChanged(Editable s) {
filterList.clear();
if (s.toString().isEmpty()) {
//you set new instance of adapter and notify old, try comment this line (below) and test it
//removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList));
adapter.notifyDataSetChanged();
} else {
Filter(s.toString());
}
}
改成这个
@Override
public void afterTextChanged(Editable s) {
if (!s.toString().isEmpty()) {
filterList.clear(); //TODO here is problem, move this to your filter method
Filter(s.toString());
} else {
//Do nothing, if the EditText field is empty the list will remain filled
}
}
还有其他方法可以解决这个问题并进行改进,但我不想混淆你,因为 android 对你来说是新体验
已编辑
您正在使用 ArrayAdapter 但我认为它是 RecyclerView,忘记 swapData 方法并尝试新的更改...抱歉
adapter.clear()
adapter.addAll(filterList);