I read How to create RecyclerView with multiple view type? but didn't understand few things.
First of all, my goal is:
I don't understand how
getItemViewType
(works in my case):public int getItemViewType(int position) { // Just as an example, return 0 or 2 depending on position // Note that unlike in ListView adapters, types don't have to be contiguous return position % 2 * 2; }
Because, I want to
set Item2 ONLY after the click not right at the beginning. This causes problems for me to understand, how to implement getItemViewType. Any pseudo code/prototype are more than welcome.
CODE: [FIRST APPROACH - Setting every second row as detail layout and try to hide it on default. Change visibility onClick method later on..]
public class DifferentRowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Model> items;
FragmentActivity c;
public DifferentRowAdapter(List<Model> items, FragmentActivity c) {
this.items = items;
this.c = c;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case MEAL_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rec_item, parent, false);
return new ViewHolder1(view);
case DETAIL_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.detail_test, parent, false);
return new ViewHolder2(view);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Model object = items.get(position);
final int currentPosition = position;
if (object != null) {
switch (object.getmType()) {
case MEAL_TYPE:
((ViewHolder1) holder).mNameTextView.setText(object.getName());
((ViewHolder1) holder).img.setImageResource(R.mipmap.ic_launcher);
break;
case DETAIL_TYPE:
((ViewHolder2) holder).detailsText.setText(object.getDescription());
break;
}
}
}
@Override
public int getItemCount() {
if (items == null)
return 0;
return items.size();
}
@Override
public int getItemViewType(int position) {
// I need ITEM2 to be at third/sixth/nineth ect. position
if(position % 3 == 0){
return DETAIL_TYPE;
}
else{
return MEAL_TYPE;
}
}
public class ViewHolder1 extends RecyclerView.ViewHolder {
TextView mNameTextView;
ImageView img;
mealsItemClickListener icl;
public ViewHolder1(View itemView) {
super(itemView);
mNameTextView = (TextView) itemView.findViewById(R.id.name);
img = (ImageView) itemView.findViewById(R.id.category_image);
}
public TextView getmNameTextView() {
return mNameTextView;
}
public void setmNameTextView(TextView mNameTextView) {
this.mNameTextView = mNameTextView;
}
public ImageView getImg() {
return img;
}
public void setImg(ImageView img) {
this.img = img;
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder {
TextView detailsText;
mealsItemClickListener icl;
public ViewHolder2(View v) {
super(v);
detailsText = (TextView) itemView.findViewById(R.id.desc);
}
public TextView getDetailsText() {
return detailsText;
}
public void setDetailsText(TextView detailsText) {
this.detailsText = detailsText;
}
}
}
[2 APPROACH - Try to add ITEM2 onClick]
public class DifferentRowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Model> items;
FragmentActivity c;
public DifferentRowAdapter(List<Model> items, FragmentActivity c) {
this.items = items;
this.c = c;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case MEAL_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rec_item, parent, false);
return new ViewHolder1(view);
case DETAIL_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.detail_test, parent, false);
return new ViewHolder2(view);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Model object = items.get(position);
final int currentPosition = position;
if (object != null) {
switch (object.getmType()) {
case MEAL_TYPE:
((ViewHolder1) holder).mNameTextView.setText(object.getName());
((ViewHolder1) holder).img.setImageResource(R.mipmap.ic_launcher);
break;
case DETAIL_TYPE:
((ViewHolder2) holder).detailsText.setText(object.getDescription());
break;
}
//THIS METHOD WORKS FINE POSITIONING WISE, BUT IT DUPLICATES CLICKED ITEM INSTEAD OF PUTTING ITEM2
((ViewHolder1) holder).img.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(c, "Position: " + currentPosition, Toast.LENGTH_SHORT).show();
addItem(currentPosition, object);
}
});
}
}
@Override
public int getItemCount() {
if (items == null)
return 0;
return items.size();
}
@Override
public int getItemViewType(int position) {
if (items != null) {
Model object = items.get(position);
if (object != null) {
return object.getmType();
}
}
return 0;
}
// Check if clicked item is left/right
private boolean isLeft(final int position){
if (position % 2 == 0){
return true; // Returns 1 if it's left columns item
}
else return false;
}
// Add item at wanted position. If left pos+2, if right+1.
private void addItem(final int position, Model object){
if(isLeft(position)){
items.add(position+2, object);
notifyItemInserted(position+2);
}
else{
items.add(position+1, object);
notifyItemInserted(position+1);
}
}
public class ViewHolder1 extends RecyclerView.ViewHolder {
TextView mNameTextView;
ImageView img;
mealsItemClickListener icl;
public ViewHolder1(View itemView) {
super(itemView);
mNameTextView = (TextView) itemView.findViewById(R.id.name);
img = (ImageView) itemView.findViewById(R.id.category_image);
}
public TextView getmNameTextView() {
return mNameTextView;
}
public void setmNameTextView(TextView mNameTextView) {
this.mNameTextView = mNameTextView;
}
public ImageView getImg() {
return img;
}
public void setImg(ImageView img) {
this.img = img;
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder {
TextView detailsText;
mealsItemClickListener icl;
public ViewHolder2(View v) {
super(v);
detailsText = (TextView) itemView.findViewById(R.id.desc);
}
public TextView getDetailsText() {
return detailsText;
}
public void setDetailsText(TextView detailsText) {
this.detailsText = detailsText;
}
}
}
TL;DR ON MY SITUATION:
Approach1: Gives me
java.lang.ClassCastException: com.example.mrti.menuapp.MULTI.DifferentRowAdapter$ViewHolder2 cannot be cast to com.example.mrti.menuapp.MULTI.DifferentRowAdapter$ViewHolder1
at com.example.mrti.menuapp.MULTI.DifferentRowAdapter.onBindViewHolder(DifferentRowAdapter.java:62)
Approach2: Adding item at certain position works fine, but it adds clicked item, not item2. I'd like to focus more on approach2, but if someone can explain first one - I'm okay with that as well. I'm not sure why it is not working, because it should be - or did I miss smth?
PROBABLY APPROACH1 SOLUTION:
In First approach, with the same position value, the value which getItemViewType(position) returns would not same to the value which items.get(position).getmType() returns.
I have to make values of type same in both getItemViewType and onBindViewHolder method;
How to do it tho?