SearchView 过滤器按预期工作,但在片段中检索 RecyclerView 上的旧项目位置
SearchView filter is working as intented, but retrieves old item position on RecyclerView in fragment
过去几天我一直在寻找我的问题的解决方案,但所有其他类似问题似乎都与 onClickListener
有关,或者他们的解决方案不适用于手头的问题.我在我的项目中使用的 onClickListeners
似乎按预期工作,只有 SearchView
不是。
我的起始列表包含一些项目及其 ingredients/materials,一切都按预期进行。当使用 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);
}
}
如果我在 Viewholder
中包含“setIsRecyclable(false)
”,问题似乎就消失了,但是在低端手机上性能很糟糕,而且卡是 destroyed/resetted他们退出视图,这不是一种理想的行为。
完整编辑 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
}
}
你能试试这个吗
class SectionRecyclerViewAdapter(
var sectionModelArrayList: ArrayList<SectionModel>,
val context: Activity
) : RecyclerView.Adapter<SectionRecyclerViewAdapter.MyViewHolder>(), Filterable {
private val mSectionList: List<SectionModel>? = sectionModelArrayList
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.section_custom_row_layout, viewGroup, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val sectionModel = sectionModelArrayList[position]
holder.tvStations.text = sectionModel.stations
holder.ivLogo.setImageDrawable(sectionModel.logo)
holder.ivArrow.setImageResource(R.mipmap.ic_arrow_dark)
holder.view.setOnClickListener {
when (position) {
0 -> {
val intent = Intent(context, AllUserActivity::class.java)
context.startActivity(intent)
context.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
}
1 -> {
Toast.makeText(context, "Nothing to Show", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun getItemCount(): Int {
return sectionModelArrayList.size
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val ivLogo: ImageView
val tvStations: TextView
val ivArrow: ImageView
val view: View
init {
ivLogo = itemView.findViewById(R.id.ivLogo)
tvStations = itemView.findViewById(R.id.tvStations)
ivArrow = itemView.findViewById(R.id.ivArrow)
view = itemView
}
}
override fun getFilter(): Filter {
return object : Filter() {
protected override fun performFiltering(charSequence: CharSequence): FilterResults {
val charString = charSequence.toString()
if (charString.isEmpty()) {
sectionModelArrayList = mSectionList as ArrayList<SectionModel>
} else {
var filteredList = ArrayList<SectionModel>()
if (mSectionList != null) {
for (row in mSectionList) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.stations.toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row)
}
}
}
sectionModelArrayList = filteredList
}
val filterResults = FilterResults()
filterResults.values = sectionModelArrayList
return filterResults
}
override fun publishResults(charSequence: CharSequence, filterResults: FilterResults) {
sectionModelArrayList = filterResults.values as ArrayList<SectionModel>
notifyDataSetChanged()
}
}
}
}
将筛选列表传递给适配器将解决问题。
如果没有全貌,很难确切地说出这里出了什么问题,但是...
你在你的 ViewHolder 中持有很多状态,比如是否是第一次,成分数量等。你真的想只持有View
在那里,因为它们可以在项目之间不可预测地交换。这就是当你告诉它它们不可回收时它起作用的原因——它不再这样做了。
您还将设置为 GONE,但如果应该显示则不可见。这是回收的问题:
holder.mIngredient_1_Icon.setVisibility(View.GONE);
您的按钮 onClick 侦听器正在修改支架中的状态 - 这很糟糕,因为支架会在项目之间交换,并且可能会反弹。你真的想要在你的 Item
class 中所有这些状态。一旦你这样做了,你的 RecyclerView 就变成了从 Item
s 到设置所有内容的 onBindViewHolder 的单向转换,推理起来会容易得多。
过去几天我一直在寻找我的问题的解决方案,但所有其他类似问题似乎都与 onClickListener
有关,或者他们的解决方案不适用于手头的问题.我在我的项目中使用的 onClickListeners
似乎按预期工作,只有 SearchView
不是。
我的起始列表包含一些项目及其 ingredients/materials,一切都按预期进行。当使用 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);
}
}
如果我在 Viewholder
中包含“setIsRecyclable(false)
”,问题似乎就消失了,但是在低端手机上性能很糟糕,而且卡是 destroyed/resetted他们退出视图,这不是一种理想的行为。
完整编辑 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
}
}
你能试试这个吗
class SectionRecyclerViewAdapter(
var sectionModelArrayList: ArrayList<SectionModel>,
val context: Activity
) : RecyclerView.Adapter<SectionRecyclerViewAdapter.MyViewHolder>(), Filterable {
private val mSectionList: List<SectionModel>? = sectionModelArrayList
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.section_custom_row_layout, viewGroup, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val sectionModel = sectionModelArrayList[position]
holder.tvStations.text = sectionModel.stations
holder.ivLogo.setImageDrawable(sectionModel.logo)
holder.ivArrow.setImageResource(R.mipmap.ic_arrow_dark)
holder.view.setOnClickListener {
when (position) {
0 -> {
val intent = Intent(context, AllUserActivity::class.java)
context.startActivity(intent)
context.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
}
1 -> {
Toast.makeText(context, "Nothing to Show", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun getItemCount(): Int {
return sectionModelArrayList.size
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val ivLogo: ImageView
val tvStations: TextView
val ivArrow: ImageView
val view: View
init {
ivLogo = itemView.findViewById(R.id.ivLogo)
tvStations = itemView.findViewById(R.id.tvStations)
ivArrow = itemView.findViewById(R.id.ivArrow)
view = itemView
}
}
override fun getFilter(): Filter {
return object : Filter() {
protected override fun performFiltering(charSequence: CharSequence): FilterResults {
val charString = charSequence.toString()
if (charString.isEmpty()) {
sectionModelArrayList = mSectionList as ArrayList<SectionModel>
} else {
var filteredList = ArrayList<SectionModel>()
if (mSectionList != null) {
for (row in mSectionList) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.stations.toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row)
}
}
}
sectionModelArrayList = filteredList
}
val filterResults = FilterResults()
filterResults.values = sectionModelArrayList
return filterResults
}
override fun publishResults(charSequence: CharSequence, filterResults: FilterResults) {
sectionModelArrayList = filterResults.values as ArrayList<SectionModel>
notifyDataSetChanged()
}
}
}
}
将筛选列表传递给适配器将解决问题。
如果没有全貌,很难确切地说出这里出了什么问题,但是...
你在你的 ViewHolder 中持有很多状态,比如是否是第一次,成分数量等。你真的想只持有View
在那里,因为它们可以在项目之间不可预测地交换。这就是当你告诉它它们不可回收时它起作用的原因——它不再这样做了。
您还将设置为 GONE,但如果应该显示则不可见。这是回收的问题:
holder.mIngredient_1_Icon.setVisibility(View.GONE);
您的按钮 onClick 侦听器正在修改支架中的状态 - 这很糟糕,因为支架会在项目之间交换,并且可能会反弹。你真的想要在你的 Item
class 中所有这些状态。一旦你这样做了,你的 RecyclerView 就变成了从 Item
s 到设置所有内容的 onBindViewHolder 的单向转换,推理起来会容易得多。