Последние несколько дней я искал решение моей проблемы, но, похоже, все другие подобные проблемы имеют проблему с onClickListener
, или их решение не предназначено для рассматриваемой проблемы. Похоже, что onClickListeners
, который я использую в своем проекте, работает так, как задумано, только SearchView
- нет.
Мой стартовый список состоит из некоторых элементов и их ингредиентов / материалов, и все работает по назначению. , При фильтрации с помощью SearchView
в новом отфильтрованном списке отображаются правильные названия элементов, но неправильные ингредиенты. Буквально старая позиция до фильтрации, и я не могу отладить, откуда возникла проблема.
MainAdapter.java
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> implements Filterable {
private List<Item> mItemCard;
private List<Item> mItemCardFull; //Needed for the getFilter() method
static class ViewHolder extends RecyclerView.ViewHolder {
// region Variables (Item Name, Icon, Expand Layout & Expand button)
ImageView mItemIcon;
TextView mItemName;
ImageButton mExpandButton;
// etc...
// region Variables (Ingredients' Icons, Names & Amount)
ImageView mIngredient_1_Icon;
TextView mIngredient_1_Name;
TextView mIngredient_1_amountTV;
float mIngredient_1_amount;
// etc...
// region misc Variables
boolean _isFirstTime = true; // Used in initialization & crafting method switch
EditText editFactoryAmount;
ImageView factoryAmountIcon;
Button factoryAmountButton;
// etc...
ViewHolder(@NonNull View itemView) {
super(itemView);
mItemIcon = itemView.findViewById(R.id.itemIcon);
mItemName = itemView.findViewById(R.id.itemName);
mIngredient_1_Icon = itemView.findViewById(R.id.ingredient_1_icon);
mIngredient_1_Name = itemView.findViewById(R.id.ingredient_1_name);
mIngredient_1_amountTV = itemView.findViewById(R.id.ingredient_1_amount);
// etc...
}
}
public MainAdapter(List<Item> itemCard) {
this.mItemCard = itemCard;
this.mItemCardFull = new ArrayList<>(itemCard);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
final ViewHolder holder = new ViewHolder(v);
return holder;
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
final Item currentItem = mItemCard.get(position);
final float craftingTime = currentItem.getCraftingTime();
final float outputAmount = currentItem.getOutputAmount();
holder.mItemIcon.setImageResource(currentItem.getItemIcon());
holder.mItemName.setText(currentItem.getItemName());
holder.mExpandButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean show = toggleLayout(!currentItem.isExpanded(), view, holder.mExpandedLayout);
currentItem.setExpanded(show);
}
});
// region Textwatchers
// region Editor Listeners
/* Editor Listener: When actionDone is clicked on the soft keyboard, clear focus from editText */
// other random methods included in the project which arent relevant
// ......
}
/* Expands or collapses depending on item state */
private boolean toggleLayout(boolean isExpanded, View v, ConstraintLayout expandedLayout) {
Animations.toggleArrow(v, isExpanded);
if (isExpanded) {
Animations.expand(expandedLayout);
} else {
Animations.collapse(expandedLayout);
}
return isExpanded;
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return mItemCard.size();
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~ Search Filter Setup ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@Override
public Filter getFilter() {
return itemFilter;
}
private Filter itemFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Item> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(mItemCardFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Item item : mItemCardFull) {
if (item.getItemName().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mItemCard.clear();
mItemCard.addAll((List) results.values);
notifyDataSetChanged();
}
};
}
IntermediatesFragment.java
public class IntermediatesFragment extends Fragment {
private RecyclerView mRecyclerView;
private MainAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
public IntermediatesFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View thisFragment = inflater.inflate(R.layout.fragment_layout, container, false);
setHasOptionsMenu(true);
mRecyclerView = thisFragment.findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getContext());
createItemList();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
return thisFragment;
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
});
}
private void createItemList() {
ArrayList<Item> itemList = new ArrayList<>();
// region Intermediates Items
// etc items ...
mAdapter = new MainAdapter(itemList);
}
}
Проблема, похоже, исчезнет go, если я включу "setIsRecyclable(false)
" в Viewholder
, но тогда производительность будет на ужасных телефонах низкого уровня, и карты будут уничтожены / сброшены при выходе из вида, который не желаемое поведение.
Редактировать с полным onBindViewHolder
:
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
final Item currentItem = mItemCard.get(position);
final float craftingTime = currentItem.getCraftingTime();
final float outputAmount = currentItem.getOutputAmount();
holder.mItemIcon.setImageResource(currentItem.getItemIcon());
holder.mItemName.setText(currentItem.getItemName());
holder.mExpandButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean show = toggleLayout(!currentItem.isExpanded(), view, holder.mExpandedLayout);
currentItem.setExpanded(show);
}
});
// region Ingredients' Icons, Names & Amounts
holder.mIngredient_1_Icon.setImageResource(currentItem.getIngredientIcon_1());
holder.mIngredient_2_Icon.setImageResource(currentItem.getIngredientIcon_2());
holder.mIngredient_3_Icon.setImageResource(currentItem.getIngredientIcon_3());
holder.mIngredient_4_Icon.setImageResource(currentItem.getIngredientIcon_4());
holder.mIngredient_5_Icon.setImageResource(currentItem.getIngredientIcon_5());
holder.mIngredient_6_Icon.setImageResource(currentItem.getIngredientIcon_6());
holder.mIngredient_1_Name.setText(currentItem.getIngredientName_1());
holder.mIngredient_2_Name.setText(currentItem.getIngredientName_2());
holder.mIngredient_3_Name.setText(currentItem.getIngredientName_3());
holder.mIngredient_4_Name.setText(currentItem.getIngredientName_4());
holder.mIngredient_5_Name.setText(currentItem.getIngredientName_5());
holder.mIngredient_6_Name.setText(currentItem.getIngredientName_6());
holder.mIngredient_1_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_1()));
holder.mIngredient_2_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_2()));
holder.mIngredient_3_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_3()));
holder.mIngredient_4_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_4()));
holder.mIngredient_5_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_5()));
holder.mIngredient_6_amountTV.setText(String.valueOf(currentItem.getIngredientAmount_6()));
if (currentItem.getIngredientName_1() == R.string.item_null) {
holder.mIngredient_1_Icon.setVisibility(View.GONE);
holder.mIngredient_1_Name.setVisibility(View.GONE);
holder.mIngredient_1_amountTV.setVisibility(View.GONE);\
// if statements continue for the rest of the 5 ingredients
// endregion Ingredients' Icons, Names & Amounts
holder.factoryAmountButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.button_f++;
float factoryAmount = Float.parseFloat(holder.editFactoryAmount.getText().toString());
float outputSpeed = Float.parseFloat((holder.editItemOutput.getText().toString()));
if (currentItem.getCraftingMethod().equals("Assembler")) {
switch (holder.button_f) {
case 0:
holder.factoryAmountIcon.setImageResource(R.drawable.pf_assembling_machine_1);
holder.craftingSpeed = 0.50f;
if (holder.editItemOutput.isFocused()) {
holder.factoryAmount = (outputSpeed * craftingTime) / ((outputAmount * holder.craftingSpeed) * (1 + (holder.speedModuleAmount * holder.speed)) * (1 + (holder.prodModuleAmount * holder.productivity)));
holder.editFactoryAmount.setText(String.valueOf(holder.factoryAmount));
// region Edit Ingredients' Amount
holder.factoryAmount = Float.parseFloat(holder.editFactoryAmount.getText().toString());
holder.mIngredient_1_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_1()) / craftingTime;
holder.mIngredient_1_amountTV.setText(String.valueOf(holder.mIngredient_1_amount));
holder.mIngredient_2_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_2()) / craftingTime;
holder.mIngredient_2_amountTV.setText(String.valueOf(holder.mIngredient_2_amount));
holder.mIngredient_3_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_3()) / craftingTime;
holder.mIngredient_3_amountTV.setText(String.valueOf(holder.mIngredient_3_amount));
holder.mIngredient_4_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_4()) / craftingTime;
holder.mIngredient_4_amountTV.setText(String.valueOf(holder.mIngredient_4_amount));
holder.mIngredient_5_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_5()) / craftingTime;
holder.mIngredient_5_amountTV.setText(String.valueOf(holder.mIngredient_5_amount));
holder.mIngredient_6_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_6()) / craftingTime;
holder.mIngredient_6_amountTV.setText(String.valueOf(holder.mIngredient_6_amount));
// it goes on in the same pattern depending on other circumstances
/*~~~~~~~~~~~~ Initialization & Crafting Method Switch ~~~~~~~~~~~~~~~~~~*/
if (holder.editFactoryAmount.getText().toString().isEmpty() && !holder.editFactoryAmount.isFocused()) {
holder.editFactoryAmount.setText(String.valueOf(1.0f));
holder.outputSpeed = ((Float.parseFloat(holder.editFactoryAmount.getText().toString()) * holder.craftingSpeed) * (1 + (holder.speedModuleAmount * holder.speed))) / craftingTime * (1 + (holder.prodModuleAmount * holder.productivity)) * outputAmount;
holder.editItemOutput.setText(String.valueOf(holder.outputSpeed));
}
float factoryAmount = Float.parseFloat(holder.editFactoryAmount.getText().toString());
switch (currentItem.getCraftingMethod()) {
case "Assembler":
// If it's the first time the app starts, set default crafting speed, else keep as it is.
if (holder._isFirstTime) {
holder.craftingSpeed = 0.50f;
holder._isFirstTime = false;
}
if (holder.craftingSpeed == 0.50f) {
holder.factoryAmountIcon.setImageResource(R.drawable.pf_assembling_machine_1);
holder.button_f = 0;
} else if (holder.craftingSpeed == 0.75f) {
holder.factoryAmountIcon.setImageResource(R.drawable.pf_assembling_machine_2);
holder.button_f = 1;
} else {
holder.factoryAmountIcon.setImageResource(R.drawable.pf_assembling_machine_3);
}
holder.outputSpeed = ((factoryAmount * holder.craftingSpeed) * (1 + (holder.speedModuleAmount * holder.speed))) / craftingTime * (1 + (holder.prodModuleAmount * holder.productivity)) * outputAmount;
holder.editItemOutput.setText(String.valueOf(holder.outputSpeed));
// region Edit Ingredients' Amount
holder.factoryAmount = Float.parseFloat(holder.editFactoryAmount.getText().toString());
holder.mIngredient_1_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_1()) / craftingTime;
holder.mIngredient_1_amountTV.setText(String.valueOf(holder.mIngredient_1_amount));
holder.mIngredient_2_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_2()) / craftingTime;
holder.mIngredient_2_amountTV.setText(String.valueOf(holder.mIngredient_2_amount));
holder.mIngredient_3_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_3()) / craftingTime;
holder.mIngredient_3_amountTV.setText(String.valueOf(holder.mIngredient_3_amount));
holder.mIngredient_4_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_4()) / craftingTime;
holder.mIngredient_4_amountTV.setText(String.valueOf(holder.mIngredient_4_amount));
holder.mIngredient_5_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_5()) / craftingTime;
holder.mIngredient_5_amountTV.setText(String.valueOf(holder.mIngredient_5_amount));
holder.mIngredient_6_amount = (holder.factoryAmount * holder.craftingSpeed * currentItem.getIngredientAmount_6()) / craftingTime;
holder.mIngredient_6_amountTV.setText(String.valueOf(holder.mIngredient_6_amount));
// endregion Edit Ingredients' Amount
break;
case "Smelter":
// thing happening here and etc for all the other cases
}
}