I am using a ExpandableRecyclerView by Big Nerd Ranch like the one in this example. The problem is whenever I try to add another sub item to my RecyclerView dynamically the space of this new item occupies the space of an item that was already there, kinda like deleting this item from the screen. I don't know how to explain it better so I've attached the following screenshots:
The above picture shows the list before addinga new sub item. When I click in the add button, I need to collapse the child view and then expand it again so it appears like bellow:
The New Item view pushes down the other child views, occupying the space that once was for the Item 2. And if I try to add a new child item to the last parent item it gives this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dietando.gabriel.dietando, PID: 4037
java.lang.IndexOutOfBoundsException: Invalid index 8, size is 8
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.remove(ArrayList.java:403)
at com.bignerdranch.expandablerecyclerview.Adapter.ExpandableRecyclerAdapter.expandParent(ExpandableRecyclerAdapter.java:319)
at com.bignerdranch.expandablerecyclerview.Adapter.ExpandableRecyclerAdapter.onParentItemClickListener(ExpandableRecyclerAdapter.java:252)
at com.bignerdranch.expandablerecyclerview.ViewHolder.ParentViewHolder.onClick(ParentViewHolder.java:200)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
When I add the new sub item, I add a new item to my array list and then call the method notifyDataSetChanged()
.
Here is my adapter code:
public class MealExpandableAdapter extends ExpandableRecyclerAdapter<MealParentViewHolder, MealChildViewHolder>
{
private Context context;
private List<ParentObject> refeicoes;
private boolean[] checkedState;
private LayoutInflater mInflater;
private MealExpandableAdapter.MealChildViewHolderListener onChildCheckChangedListener;
public interface MealChildViewHolderListener
{
public void onCheckChange(int mealNumber, Food food, boolean selected);
}
public MealExpandableAdapter(Context context, List<ParentObject> refeicoes)
{
super(context, refeicoes);
this.context = context;
this.refeicoes = refeicoes;
mInflater = LayoutInflater.from(context);
checkedState = new boolean[refeicoes.size()];
for(int i = 0; i < checkedState.length; ++i)
checkedState[i] = false;
}
protected void setOnChilCheckedChangedListener(MealExpandableAdapter.MealChildViewHolderListener onChildCheckChangedListener)
{
this.onChildCheckChangedListener = onChildCheckChangedListener;
}
@Override
public MealParentViewHolder onCreateParentViewHolder(ViewGroup viewGroup)
{
View view = mInflater.inflate(R.layout.adapter_refeicao, viewGroup, false);
return new MealParentViewHolder(view);
}
@Override
public MealChildViewHolder onCreateChildViewHolder(ViewGroup viewGroup)
{
View view = mInflater.inflate(R.layout.adapter_refeicao_child, viewGroup, false);
return new MealChildViewHolder(view);
}
@Override
public void onBindParentViewHolder(MealParentViewHolder mealParentViewHolder, final int mealNumber, Object parentObject)
{
final Meal meal = (Meal) parentObject;
mealParentViewHolder.mMealParentTextView.setText(meal.getNome());
mealParentViewHolder.mMealParentImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("Teste", "img btn click");
meal.addFood(0, new Food("New item", 30, 30, 30));
//notify();
//notifyItemInserted(mealNumber);
notifyDataSetChanged();
notifyItemChanged(mealNumber);
}
});
}
@Override
public void onBindChildViewHolder(final MealChildViewHolder mealChildViewHolder, final int mealNumber, Object childObject)
{
//final Meal meal = (Meal) refeicoes.get(mealNumber);
final Food food = (Food) childObject;
mealChildViewHolder.mMealChildTextView.setText(food.getName());
mealChildViewHolder.mMealChildCheckBox.setChecked(food.isChecked());
mealChildViewHolder.mMealChildCheckBox.setChecked(food.isChecked());
mealChildViewHolder.mMealChildCheckBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((CheckBox) v).isChecked()) {
Log.i("Teste", "checked");
food.checkFood();
onChildCheckChangedListener.onCheckChange(mealNumber, food, true);
} else {
Log.i("Teste", "unchecked");
food.checkFood();
onChildCheckChangedListener.onCheckChange(mealNumber, food, false);
}
}
});
}
Here is my ParentViewHolder:
public class MealParentViewHolder extends ParentViewHolder
{
public TextView mMealParentTextView;
public ImageButton mMealParentImageButton;
public CheckBox mMealParentCheckBox;
public MealParentViewHolder(View itemView)
{
super(itemView);
mMealParentTextView = (TextView) itemView.findViewById(R.id.tTitle);
mMealParentImageButton = (ImageButton) itemView.findViewById(R.id.imgBtnParent);
mMealParentCheckBox = (CheckBox) itemView.findViewById(R.id.checkBox);
}
}
And here is my ChildViewHolder
public class MealChildViewHolder extends ChildViewHolder
{
public TextView mMealChildTextView;
public CheckBox mMealChildCheckBox;
public MealChildViewHolder(View itemView)
{
super(itemView);
mMealChildTextView = (TextView) itemView.findViewById(R.id.txtFragMeal);
mMealChildCheckBox = (CheckBox) itemView.findViewById(R.id.checkBoxFragMeal);
mMealChildCheckBox.setChecked(false);
mMealChildCheckBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((CheckBox) v).isChecked()) {
Log.i("Teste", "checked");
} else {
}
}
});
}
}
That's how I'm initalizing the ViewHolder in my Fragment:
RecyclerView recyclerView = (RecyclerView) getView().findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
meals = user.getDiet().getMeals();
MealExpandableAdapter mMealExpandableAdapter = new MealExpandableAdapter(getActivity(), meals);
mMealExpandableAdapter.setOnChilCheckedChangedListener(onChildCheckChangedListener());
// mCrimeExpandableAdapter.setCustomParentAnimationViewId(R.id.parent_list_item_expand_arrow);
mMealExpandableAdapter.setParentClickableViewAnimationDefaultDuration();
mMealExpandableAdapter.setParentAndIconExpandOnClick(true);
recyclerView.setAdapter(mMealExpandableAdapter);
I think the problem is with the adapter but I have no idea what's wrong, I''l appreciate any help.