问题描述
我正在编写一个程序,以便能够通过 recyclerview 查看设备上 app 文件夹中的文件,并删除它们。
mainactivity 处理文件删除和删除,adapter 处理在 onclicks 中查找位置和视觉变化
我实现了一个搜索过滤器,以便用户可以找到文件。我的主要活动实际上从过滤器中获取正确的位置,并在删除文件时删除它们,并在单击时在吐司消息中显示正确的路径。同样,该行会暂时从视图中删除,直到我更改搜索。
但是,在适配器中没有正确处理视觉变化。文件名在被删除后仍保留在视图中(尽管如果我显然重新启动程序,它就会消失,因为 rowItem 列表是从设备上的文件重新创建的)。在我尝试从列表中删除文件名后,应用于已删除项目的视觉更改(即通过单击菜单图标展开菜单)出现在其他文件名上,其索引与已删除文件在搜索中的索引相同。我看到了其他类似的问题,但无法使用它们来解决我的问题
我很困惑,因为我似乎在过滤时更新了我的列表
我的行适配器:
public class RowAdapter extends RecyclerView.Adapter<RowAdapter.RowViewHolder> implements Filterable{
private ArrayList<RowItem> rowList;
public ArrayList<RowItem> rowListAll;
private OnItemClickListener rowListener;
public RowAdapter(ArrayList<RowItem> rowList){
this.rowList = rowList;
this.rowListAll = new ArrayList<>(rowList);
}
public interface OnItemClickListener{
void onItemClick(int position);
void onDeleteClick(int position);
void onMenuClick(int position);
}
public void setonItemClickListener(OnItemClickListener listener){
rowListener = listener;
}
public static class RowViewHolder extends RecyclerView.ViewHolder{
public ImageView rowImageView;
public TextView rowTextView;
public Button rowDeleteButton;
public Button rowSendButton;
public ImageView rowMenuIcon;
public RowViewHolder(@NonNull View itemView,OnItemClickListener listener) {
super(itemView);
//find views in row XML
rowImageView = itemView.findViewById(R.id.fileImage);
rowTextView = itemView.findViewById(R.id.fileName);
rowDeleteButton = itemView.findViewById(R.id.deleteFile);
rowSendButton = itemView.findViewById(R.id.editButton);
rowMenuIcon = itemView.findViewById(R.id.menuIcon);
//handle adapters onclick behavior of the recyclerview. Using to handle visual changes in the XML as well
itemView.setonClickListener(v -> {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(position);
rowDeleteButton.setVisibility(View.INVISIBLE); rowSendButton.setVisibility(View.INVISIBLE); rowMenuIcon.setVisibility(View.VISIBLE);
rowTextView.setTextColor(Color.parseColor("#000000"));
}
}
});
rowMenuIcon.setonClickListener(v -> {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onMenuClick(position);
rowDeleteButton.setVisibility(View.VISIBLE); rowSendButton.setVisibility(View.VISIBLE); rowMenuIcon.setVisibility(View.INVISIBLE);
rowTextView.setTextColor(Color.parseColor("#808e95"));
}
}
});
rowDeleteButton.setonClickListener(v -> {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onDeleteClick(position);
}
}
});
}
}
@NonNull
@Override
public RowViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row,parent,false);
return new RowViewHolder(v,rowListener);
}
@Override
public void onBindViewHolder(@NonNull RowViewHolder holder,int position) {
String currentItem = rowList.get(position).getFileName();
holder.rowTextView.setText(currentItem);
}
//return the # of items in the recyclerview
@Override
public int getItemCount() {
return rowList.size();
}
/////////////SEARCH FILTER METHODS////////////////////
@Override
public Filter getFilter() {
return filter;
}
Filter filter = new Filter() {
//runs on background thread
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<RowItem> filtredList = new ArrayList<>();
//add all to the filtred list if searchtext is empty
if(constraint.toString().isEmpty()){
filtredList.addAll(rowListAll);
}
//else check if filename in the row item matches the searchtext,if it does add the row item to the filtred list
else{
for (RowItem row: rowListAll){
if(row.getFileName().toLowerCase().contains(constraint.toString().toLowerCase())){
filtredList.add(row);
}
}
}
//create a filterResults variable to hold the filtred results to the publishResults method
FilterResults filterResults = new FilterResults();
filterResults.values = filtredList;
return filterResults;
}
//runs on UI thread
@Override
protected void publishResults(CharSequence constraint,FilterResults results) {
rowList.clear();
rowList.addAll((Collection<? extends RowItem>) results.values);
notifyDataSetChanged();
}
};
}
MainActivity(称为 FileView)
public class FileView extends AppCompatActivity {
private RecyclerView fileRecyclerView;
private RowAdapter fileAdapter;
private RecyclerView.LayoutManager fileLayoutManager;
private ArrayList<RowItem> rowItem;
private File[] files;
private File tempFile;
private File selectedFileData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_view);
//Create a array of files in the app folder named PDF_files sorted in descending order
File file = new File(getExternalFilesDir("PDF_files").toString());
files = file.listFiles();
Arrays.sort(files,Collections.reverSEOrder());
createRows();
buildrecyclerView();
}
public void createRows(){
rowItem = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
tempFile = files[i];
rowItem.add(new RowItem(tempFile.getName().replace("__","\n").replace('_',' ').replace('-','/').replace(".pdf",""),tempFile));
}
}
public void buildrecyclerView() {
fileRecyclerView = findViewById(R.id.recyclerView);
fileRecyclerView.setHasFixedSize(true);
fileLayoutManager = new linearlayoutmanager(this);
fileAdapter = new RowAdapter(rowItem);
fileRecyclerView.setLayoutManager(fileLayoutManager);
fileRecyclerView.setAdapter(fileAdapter);
fileAdapter.setonItemClickListener(new RowAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
selectedFileData = rowItem.get(position).getFileData();
Toast.makeText(FileView.this,"Clicked: " + selectedFileData.getPath(),Toast.LENGTH_SHORT).show();
}
@Override
public void onDeleteClick(int position) {
selectedFileData = rowItem.get(position).getFileData();
selectedFileData.delete();
Toast.makeText(FileView.this,"Deleted: " + selectedFileData.getPath(),Toast.LENGTH_SHORT).show();
removeItem(position);
}
@Override
public void onMenuClick(int position) {
}
});
}
public void removeItem(int position) {
rowItem.remove(position);
fileAdapter.notifyItemRemoved(position);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu,menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) item.getActionView();
searchView.setonQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
fileAdapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}
解决方法
所以我实现了一个修复,但对我来说似乎有点麻烦,必须再次传递 arraylist 的值,而不是在单击时在适配器中删除它
在 FileView/mainactivity 中更改了我的 removeItem 方法:
public void removeItem(int position) {
rowItem.remove(position);
fileAdapter = new RowAdapter(rowItem);
}
而且,我通过将它们放在 onBindViewHolder 中来以不同的方式处理适配器中的视觉变化
@Override
public void onBindViewHolder(@NonNull RowViewHolder holder,int position) {
RowItem currentRow = rowList.get(position);
String currentItem = rowList.get(position).getFileName();
holder.rowTextView.setText(currentItem);
//handle visual changes
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.rowDeleteButton.setVisibility(View.INVISIBLE); holder.rowSendButton.setVisibility(View.INVISIBLE); holder.rowMenuIcon.setVisibility(View.VISIBLE);
holder.rowTextView.setTextColor(Color.parseColor("#000000"));
Log.d("LOG",currentItem.toString());
}
});
holder.rowMenuIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.rowDeleteButton.setVisibility(View.VISIBLE); holder.rowSendButton.setVisibility(View.VISIBLE); holder.rowMenuIcon.setVisibility(View.INVISIBLE);
holder.rowTextView.setTextColor(Color.parseColor("#808e95"));
}
});
}
想知道是否有更好的方法