Here is a video of the behavior of the app that I am trying to explain just in case if you didn't understand my explanation of the problem. See the link below...
https://file.re/2021/09/14/2021-09-1405-16-22/
I am trying to develop an android app that has several card view layouts that will be displayed in one recycler view. I am not having much luck getting the recycler view to list the layouts like I want it to. I can add the first layout just fine, and then add the second layout just as long as the first card view layout exists in the recycler view. If it doesn't exists in the recycler view, and I try adding the second card view layout first by clicking on the button to add it a couple times, it will add it along with the first card view layout. Also, when trying to remove the card views from the layout they are not removing correctly. Here is what I have in my java code...
MainActivity.Java
public class MainActivity extends AppCompatActivity {
ArrayList<RecyclerItem> addConverterCard = new ArrayList<>();
private RecyclerView recyclerView;
private RecyclerItemAdapter recyclerItemAdapter;
private RecyclerView.LayoutManager layoutManager;
public TextView ftocConverterLabelBtn, ftokConverterLabelBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_item_view);
ftocConverterLabelBtn = findViewById(R.id.add_f_to_c_converter_label_btn);
ftokConverterLabelBtn = findViewById(R.id.add_f_to_k_converter_label_btn);
ftocConverterLabelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clicked) {
addConverterCard.add(new RecyclerItem());
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(MainActivity.this);
recyclerItemAdapter = new RecyclerItemAdapter(addConverterCard);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerItemAdapter);
recyclerItemAdapter.notifyDataSetChanged();
closeActionButton();
}
}
});
ftokConverterLabelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clicked) {
addConverterCard.add(new RecyclerItem());
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(MainActivity.this);
recyclerItemAdapter = new RecyclerItemAdapter(addConverterCard);
recyclerView.setLayoutManager(layoutManager);
recyclerItemAdapter.notifyDataSetChanged();
closeActionButton();
}
}
});
Adapter.Java
public static class RecyclerItemAdapter extends RecyclerView.Adapter<RecyclerItemAdapter.RecyclerViewHolder> {
public ArrayList<RecyclerItem> recyclerItemList;
public AdapterView.OnItemClickListener recyclerItemListener;
public List<String> converterType;
public interface OnItemClickListener {
void onItemClick (int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
recyclerItemListener = (AdapterView.OnItemClickListener) listener;
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert);
convertResult = itemView.findViewById(R.id.output_result_ftc);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn);
deleteCardBtn = itemView.findViewById(R.id.remove_card);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public static class RecyclerViewHolder2 extends RecyclerViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder2(#NonNull View itemView, final OnItemClickListener listener2) {
super(itemView, listener2);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert2);
convertResult = itemView.findViewById(R.id.output_result_ftk);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn2);
deleteCardBtn = itemView.findViewById(R.id.remove_card2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener2 != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener2.onItemClick(position);
}
}
}
});
}
}
#Override
public int getItemViewType(int position) {
return position % 2 * 2;
}
public RecyclerItemAdapter(ArrayList<RecyclerItem> rList) {
recyclerItemList = rList;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_celsius_converter_layout, parent, false);
RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(v, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder;
case 2:
View v2 = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_kelvin_converter_layout, parent, false);
RecyclerViewHolder2 recyclerViewHolder2 = new RecyclerViewHolder2(v2, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder2;
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0: RecyclerViewHolder viewHolder = (RecyclerViewHolder) holder;
RecyclerItem currentItem = recyclerItemList.get(position);
final String[] result = new String[1];
viewHolder.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {...}
viewHolder.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(viewHolder.getLayoutPosition());
}
});
break;
case 2: RecyclerViewHolder2 viewHolder2 = (RecyclerViewHolder2)holder;
RecyclerItem currentItem2 = recyclerItemList.get(position);
final String[] result2 = new String[1];
viewHolder2.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {...}
viewHolder2.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(viewHolder2.getLayoutPosition());
}
});
break;
}
}
#Override
public int getItemCount() {
return recyclerItemList.size();
}
public void removeCard(int position) {
recyclerItemList.remove(position);
notifyItemRemoved(position);
}
}
public class RecyclerItem {
public RecyclerItem() {
}
}
I appreciate your help!
Full Adapter Class
public static class RecyclerItemAdapter extends RecyclerView.Adapter<RecyclerItemAdapter.RecyclerViewHolder> {
public ArrayList<RecyclerItem> recyclerItemList;
public AdapterView.OnItemClickListener recyclerItemListener;
public List<String> converterType;
public interface OnItemClickListener {
void onItemClick (int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
recyclerItemListener = (AdapterView.OnItemClickListener) listener;
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert);
convertResult = itemView.findViewById(R.id.output_result_ftc);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn);
deleteCardBtn = itemView.findViewById(R.id.remove_card);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public static class RecyclerViewHolder2 extends RecyclerViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder2(#NonNull View itemView, final OnItemClickListener listener2) {
super(itemView, listener2);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert2);
convertResult = itemView.findViewById(R.id.output_result_ftk);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn2);
deleteCardBtn = itemView.findViewById(R.id.remove_card2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener2 != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener2.onItemClick(position);
}
}
}
});
}
}
#Override
public int getItemViewType(int position) {
return recyclerItemList.get(position).getType;
}
public RecyclerItemAdapter(ArrayList<RecyclerItem> rList) {
recyclerItemList = rList;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_celsius_converter_layout, parent, false);
RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(v, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder;
case 1:
View v2 = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_kelvin_converter_layout, parent, false);
RecyclerViewHolder2 recyclerViewHolder2 = new RecyclerViewHolder2(v2, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder2;
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0: RecyclerViewHolder viewHolder = (RecyclerViewHolder) holder;
RecyclerItem currentItem = recyclerItemList.get(position);
final String[] result = new String[1];
viewHolder.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View view) {
String getIputFahValue = viewHolder.inputFahValueET.getText().toString();
NumberFormat nf = new DecimalFormat("0.000");
if (!getIputFahValue.isEmpty()) {
double d = Double.parseDouble(getIputFahValue);
double dd = d - 32;
double ddd = dd * 5;
double dddd = ddd / 9;
result[0] = Double.toString(dddd);
viewHolder.convertResult.setText(nf.format(dddd) + "°C");
viewHolder.convertResult.setVisibility(View.VISIBLE);
viewHolder.shortResult = nf.format(dddd) + "°C";
viewHolder.longResult = getIputFahValue + "°F is " + nf.format(dddd) + "°C";
if (result[0].contains(".0")) {
result[0] = result[0].replace(".0", "");
viewHolder.convertResult.setText(result[0] + "°C");
viewHolder.convertResult.setVisibility(View.VISIBLE);
viewHolder.shortResult = result[0] + "°C";
viewHolder.longResult = getIputFahValue + "°F is " + result[0] + "°C";
} else if (result[0].contains(".000")) {
result[0] = result[0].replace(".000", "");
viewHolder.convertResult.setText(result[0] + "°C");
viewHolder.convertResult.setVisibility(View.VISIBLE);
viewHolder.shortResult = result[0] + "°C";
viewHolder.longResult = getIputFahValue + "°F is " + result[0] + "°C";
}
} else {
Toast.makeText(view.getContext(), "Fahrenheit Value Field Cannot Be Blank!", Toast.LENGTH_LONG).show();
}
}
});
viewHolder.convertResult.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
AlertDialog.Builder adb = new AlertDialog.Builder(view.getContext());
adb.setIcon(R.drawable.ic_baseline_file_copy_32);
adb.setTitle("Copy Result");
adb.setMessage("You can copy the result to your clipboard if you would like. Choose if you want the short or long result copied to your clipboard.\n\nExample of Short and Long Result:\nShort Result: 32°C\nLong Result: 0°F is 32°C");
adb.setPositiveButton("Short", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ClipboardManager cbm = (ClipboardManager) view.getContext().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copy", holder.shortResult);
cbm.setPrimaryClip(clip);
Toast.makeText(view.getContext(), "Result Copied!", Toast.LENGTH_SHORT).show();
}
});
adb.setNegativeButton("Long", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ClipboardManager cbm = (ClipboardManager) view.getContext().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copy", holder.longResult);
cbm.setPrimaryClip(clip);
Toast.makeText(view.getContext(), "Result Copied!", Toast.LENGTH_SHORT).show();
}
});
adb.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
adb.create();
adb.show();
return false;
}
});
viewHolder.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(viewHolder.ge);
}
});
break;
case 2: RecyclerViewHolder2 viewHolder2 = (RecyclerViewHolder2)holder;
RecyclerItem currentItem2 = recyclerItemList.get(position);
final String[] result2 = new String[1];
viewHolder2.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View view) {
String getIputFahValue = viewHolder2.inputFahValueET.getText().toString();
NumberFormat nf = new DecimalFormat("0.000");
if (!getIputFahValue.isEmpty()) {
double d = Double.parseDouble(getIputFahValue);
double dd = d - 32;
double ddd = dd * 5;
double dddd = ddd / 9;
double ddddd = dddd + 273.15;
result2[0] = Double.toString(ddddd);
viewHolder2.convertResult.setText(nf.format(ddddd) + "°K");
viewHolder2.convertResult.setVisibility(View.VISIBLE);
viewHolder2.shortResult = nf.format(dddd) + "°K";
viewHolder2.longResult = getIputFahValue + "°F is " + nf.format(dddd) + "°K";
if (result2[0].contains(".0")) {
result2[0] = result2[0].replace(".0", "");
viewHolder2.convertResult.setText(result2[0] + "°K");
viewHolder2.convertResult.setVisibility(View.VISIBLE);
viewHolder2.shortResult = result2[0] + "°K";
viewHolder2.longResult = getIputFahValue + "°F is " + result2[0] + "°K";
} else if (result2[0].contains(".000")) {
result2[0] = result2[0].replace(".000", "");
viewHolder2.convertResult.setText(result2[0] + "°K");
viewHolder2.convertResult.setVisibility(View.VISIBLE);
viewHolder2.shortResult = result2[0] + "°K";
viewHolder2.longResult = getIputFahValue + "°F is " + result2[0] + "°K";
}
} else {
Toast.makeText(view.getContext(), "Fahrenheit Value Field Cannot Be Blank!", Toast.LENGTH_LONG).show();
}
}
});
viewHolder2.convertResult.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
AlertDialog.Builder adb = new AlertDialog.Builder(view.getContext());
adb.setIcon(R.drawable.ic_baseline_file_copy_32);
adb.setTitle("Copy Result");
adb.setMessage("You can copy the result to your clipboard if you would like. Choose if you want the short or long result copied to your clipboard.\n\nExample of Short and Long Result:\nShort Result: 283.15°K\nLong Result: 50°F is 283.15°K");
adb.setPositiveButton("Short", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ClipboardManager cbm = (ClipboardManager) view.getContext().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copy", holder.shortResult);
cbm.setPrimaryClip(clip);
Toast.makeText(view.getContext(), "Result Copied!", Toast.LENGTH_SHORT).show();
}
});
adb.setNegativeButton("Long", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ClipboardManager cbm = (ClipboardManager) view.getContext().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copy", holder.longResult);
cbm.setPrimaryClip(clip);
Toast.makeText(view.getContext(), "Result Copied!", Toast.LENGTH_SHORT).show();
}
});
adb.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
adb.create();
adb.show();
return false;
}
});
viewHolder2.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(viewHolder2.getLayoutPosition());
}
});
break;
}
}
#Override
public int getItemCount() {
return recyclerItemList.size();
}
public void removeCard(int position) {
recyclerItemList.remove(position);
notifyItemRemoved(position);
}
}
public static class RecyclerItem {
public int getType;
int type;
public RecyclerItem(int mType) {
this.getType = mType;
}
public int getType() {
return type();
}
private int type() {
return type;
}
}
}
well there's some mistakes I suspect so I will try and suggest some things maybe it fixes your code behavior.
in removing the card, consider using holder.getAbsoluteAdapterPosition() instead of viewHolder.getLayoutPosition() or getAdapterPosition.
on adding any card, stop creating a new Adapter and LayoutManager over and over again, this components should be created once for any RecylcerView, just keep a reference to only the first old created adapter as a global variable, add the new card to the data ArrayList that the old adapter has reference to, use adapter.notifyDataSetChanged() on the old adapter reference that you're keeping as global variable.
I don't know how the viewType algorithm works, but if the options from add button decide which one you want, store an index to which card you want in the RecyclerItem object itself and in getItemViewType that you're overriding get the item at the required position and return its stored type rather than this strange position calculation (position%2*2).
by doing that make switch cases according to the integer values that you will be storing in ftoc/ftok/...etcConverterLabelBtn.setOnClickListener.
that would be a solution that it doesn't add or delete the right type of card in correspondence to your add/delete choices since your viewType algorithm will return value based on just the position not your choice.
anytime I used setHasFixedSize(true) it caused me trouble, so if you don't have a good reason to be using this, I suggest that you delete/comment its line of code completely
Update
your code should be looking like this :
Main Activity
public class MainActivity extends AppCompatActivity {
ArrayList<RecyclerItem> addConverterCard ;
private RecyclerView recyclerView;
private RecyclerItemAdapter recyclerItemAdapter;
private RecyclerView.LayoutManager layoutManager;
public TextView ftocConverterLabelBtn, ftokConverterLabelBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_item_view);
ftocConverterLabelBtn = findViewById(R.id.add_f_to_c_converter_label_btn);
ftokConverterLabelBtn = findViewById(R.id.add_f_to_k_converter_label_btn);
addConverterCard = new ArrayList<>();
recyclerItemAdapter = new RecyclerItemAdapter(addConverterCard);
layoutManager = new LinearLayoutManager(MainActivity.this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerItemAdapter);
ftocConverterLabelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clicked) {
addConverterCard.add(new RecyclerItem(0));
recyclerItemAdapter.notifyDataSetChanged();
closeActionButton();
}
}
});
ftokConverterLabelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clicked) {
addConverterCard.add(new RecyclerItem(1));
recyclerItemAdapter.notifyDataSetChanged();
closeActionButton();
}
}
});
Adapter code
public static class RecyclerItemAdapter extends RecyclerView.Adapter<RecyclerItemAdapter.RecyclerViewHolder> {
public ArrayList<RecyclerItem> recyclerItemList;
public AdapterView.OnItemClickListener recyclerItemListener;
public List<String> converterType;
public interface OnItemClickListener {
void onItemClick (int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
recyclerItemListener = (AdapterView.OnItemClickListener) listener;
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert);
convertResult = itemView.findViewById(R.id.output_result_ftc);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn);
deleteCardBtn = itemView.findViewById(R.id.remove_card);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
int position = getAbsoluteAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public static class RecyclerViewHolder2 extends RecyclerViewHolder {
EditText inputFahValueET;
TextView convertResult;
ImageView tempIconAndConvertBtn;
ImageView deleteCardBtn;
String shortResult, longResult;
public RecyclerViewHolder2(#NonNull View itemView, final OnItemClickListener listener2) {
super(itemView, listener2);
inputFahValueET = itemView.findViewById(R.id.input_fahrenheit_value_to_convert2);
convertResult = itemView.findViewById(R.id.output_result_ftk);
tempIconAndConvertBtn = itemView.findViewById(R.id.temp_icon_convert_btn2);
deleteCardBtn = itemView.findViewById(R.id.remove_card2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener2 != null) {
int position = getAbsoluteAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener2.onItemClick(position);
}
}
}
});
}
}
#Override
public int getItemViewType(int position) {
return recyclerItemList.get(position).getType();
}
public RecyclerItemAdapter(ArrayList<RecyclerItem> rList) {
recyclerItemList = rList;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_celsius_converter_layout, parent, false);
RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(v, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder;
case 1:
View v2 = LayoutInflater.from(parent.getContext()).inflate(R.layout.fahrenheit_to_kelvin_converter_layout, parent, false);
RecyclerViewHolder2 recyclerViewHolder2 = new RecyclerViewHolder2(v2, (OnItemClickListener) recyclerItemListener);
return recyclerViewHolder2;
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0: RecyclerViewHolder viewHolder = (RecyclerViewHolder) holder;
RecyclerItem currentItem = recyclerItemList.get(position);
final String[] result = new String[1];
viewHolder.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {...});
viewHolder.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(holder.getAbsoluteAdapterPosition());
}
});
break;
case 1: RecyclerViewHolder2 viewHolder2 = (RecyclerViewHolder2)holder;
RecyclerItem currentItem2 = recyclerItemList.get(position);
final String[] result2 = new String[1];
viewHolder2.tempIconAndConvertBtn.setOnClickListener(new View.OnClickListener() {...});
viewHolder2.deleteCardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeCard(holder.getAbsoluteAdapterPosition());
}
});
break;
}
}
#Override
public int getItemCount() {
return recyclerItemList.size();
}
public void removeCard(int position) {
recyclerItemList.remove(position);
notifyItemRemoved(position);
}
public class RecyclerItem {
int type ;
public RecyclerItem(int m_type) {
this.type = m_type ;
}
public int getType(){
return type;
}
}
}
Related
I have created a Nested recycle rview with parent and child both dynamic.Addition to both Parent and Child is working fine.Deletion from child is working fine.I want to remove parent view when all the child views for the same is removed.Confused about how could i implement the same.
Here is the child Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<ToDoModel> values;
private Context context;
//private OnEditListener onEditListener;
AlertDialog alertDialog;
/*public MyAdapter(List<ToDoModel> context) {
this.values = context;
this.onEditListener = onEditListener;
}*/
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtHeader;
public TextView txtFooter;
public ImageView mIcon;
public View layout;
public ImageView deleteItem;
public CheckBox doneButton;
public ImageView editItem;
public ViewHolder(View v) {
super(v);
layout = v;
txtHeader = (TextView) v.findViewById(R.id.firstLine);
txtFooter = (TextView) v.findViewById(R.id.secondLine);
mIcon = (ImageView) v.findViewById(R.id.icon);
deleteItem = (ImageView) v.findViewById(R.id.deleteButton);
doneButton = (CheckBox) v.findViewById(R.id.checkBox);
editItem = (ImageView) v.findViewById(R.id.editButton);
}
}
public void add(int position, ToDoModel item) {
values.add(position, item);
sort();
notifyDataSetChanged();
//notifyItemInserted(position);
}
public void replace(ToDoModel item)
{
int editPos;
editPos = values.indexOf(item);
values.set(editPos,item);
sort();
notifyDataSetChanged();
}
public void sort() {
if ((int) values.size() > 1) {
Collections.sort(values);
}
}
public void remove(int position) {
values.remove(position);
notifyDataSetChanged();
}
public MyAdapter(List<ToDoModel> myDataset) {
values = myDataset;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
LayoutInflater inflater = LayoutInflater.from(
parent.getContext());
View v =
inflater.inflate(R.layout.todo_row_view, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final ToDoModel toDoModel = values.get(position);
switch ((String) toDoModel.task) {
case "To Go":
holder.mIcon.setImageResource(R.drawable.ic_explore24px);
break;
case "To Get":
holder.mIcon.setImageResource(R.drawable.ic_shoppingbag24px);
break;
case "To Do":
holder.mIcon.setImageResource(R.drawable.ic_todo);
break;
default:
break;
}
holder.txtHeader.setText(toDoModel.header);
holder.txtFooter.setText(toDoModel.task + " | " + toDoModel.tod + " | " + toDoModel.footer);
holder.doneButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isChecked()) {
//holder.mIcon.setImageResource(R.drawable.ic_check_circle24px);
Toast.makeText(buttonView.getContext(), "Marked As Done", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(buttonView.getContext(), "Marked As UnDone", Toast.LENGTH_SHORT).show();
}
}
});
holder.deleteItem.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
View view = LayoutInflater.from(v.getContext()).inflate(R.layout.delete_promptdialog,null);
Button YesButton = (Button) view.findViewById(R.id.buttonYes);
Button NoButton = (Button) view.findViewById(R.id.buttonNo);
YesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
remove(position);
Toast.makeText(v.getContext(), "List Item Removed", Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}
});
NoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Delete Canceled", Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}
});
builder.setView(view);
alertDialog=builder.create();
alertDialog.show();
/*remove(position);
Toast.makeText(v.getContext(), "List Item Removed", Toast.LENGTH_SHORT).show();*/
}
});
/* holder.editItem.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onEditListener.onEditClick(values.get(position));
//Toast.makeText(v.getContext(), "List Edit", Toast.LENGTH_SHORT).show();
}
});*/
}
/*public interface OnEditListener {
void onEditClick(ToDoModel currentData);
}*/
#Override
public int getItemCount() {
return values.size();
}
}
Here is the Parent Adapter
public class ParentAdapter extends RecyclerView.Adapter<ParentAdapter.ParentViewHolder> {
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
public List<TodoParent> parentList;
public TodoParent todayList;
public static long todayEpochDate;
public ParentAdapter(List<TodoParent> parentList, MainFragment mainFragment) {
this.parentList = parentList;
}
public void add(int position, TodoParent item) {
parentList.add(position, item);
sort();
notifyDataSetChanged();
//notifyItemInserted(position);
}
public void sort() {
if ((int) parentList.size() > 1) {
Collections.sort(parentList);
//if(!(todayList.ParentTitle.isEmpty())) Collections.swap(parentList, parentList.indexOf(todayList), 0);
}
/* if ( todayList )
{
System.out.println("Entering Swap");
setToday(todayList);
}*/
}
public void setToday(TodoParent item) {
int todayPos;
todayPos = parentList.indexOf(item);
parentList.remove(todayPos);
notifyDataSetChanged();
parentList.add(0,item);
notifyDataSetChanged();
}
#NonNull
#Override
public ParentAdapter.ParentViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.todo_parent_view,parent,false);
ParentViewHolder vh = new ParentViewHolder(view);
return vh;
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(#NonNull ParentViewHolder holder, int position) {
TodoParent todoParent = parentList.get(position);
todoParent.ParentId = position;
Calendar mCal;
mCal = Calendar.getInstance();
int mDay = mCal.get(Calendar.DAY_OF_MONTH);
int mMonth = mCal.get(Calendar.MONTH);
int mYear = mCal.get(Calendar.YEAR);
String dateString = mDay +"/"+ (mMonth+1) +"/" + mYear;
try {
todayEpochDate = new SimpleDateFormat("dd/MM/yyyy").parse(dateString).getTime()/1000;
} catch (ParseException e) {
e.printStackTrace();
}
if((long)todayEpochDate == (long)todoParent.EpochTime)
{
holder.mTitle.setText("Today");
todayList = todoParent;
System.out.println("todayE:"+todayEpochDate);
System.out.println("SelectedE:"+todoParent.EpochTime);
}
else
{
holder.mTitle.setText(todoParent.ParentTitle);
System.out.println("today:"+todayEpochDate);
System.out.println("Selected:"+todoParent.EpochTime);
}
LinearLayoutManager layoutManager = new LinearLayoutManager(holder.childView.getContext(),
LinearLayoutManager.VERTICAL,false);
layoutManager.setInitialPrefetchItemCount(todoParent.mChildList.size());
holder.childView.setLayoutManager(layoutManager);
MyAdapter myAdapter = new MyAdapter(todoParent.mChildList);
holder.childView.setAdapter(myAdapter);
holder.childView.setRecycledViewPool(viewPool);
}
#Override
public int getItemCount() {
return parentList.size();
}
public class ParentViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public RecyclerView childView;
public ParentViewHolder(#NonNull View itemView) {
super(itemView);
mTitle = itemView.findViewById(R.id.mParentTitle);
childView = itemView.findViewById(R.id.mChildView);
}
}
}
remove for child is working fine. How to remove Parent here when there are no more child views?
My problem is that I have a recycler view that opens a dialog when a tap on them, but when rapidly tap on two different item it opens two dialog.
How can I solve this?.
I've tried
using a bool before the click action:
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
if(!clicked[0]){
clicked[0] = true;
if (mListener != null) {
mListener.onClickBoard(mValues.get(i));
}else{
((MainActivity)mContext).onClickBoard(mValues.get(i).getAreaId(), mValues.get(i).getName());
}
}
}
})
but this just solve the case when I double tap the same item, but not when I tap different items fast.
hope you can help me, what should I do.
EDIT
I would prefer to solve it from the adapter because I will use the solution for other recycler views, and the others don't call a dialog.
My Adapter Class:
public class MyBoardAdapter extends RecyclerView.Adapter<MyBoardAdapter.ViewHolder> {
private List<Board> mValues;
private Context mContext;
private final OnBoardFragmentInteractionListener mListener;
public MyBoardAdapter(List<Board> mValues, OnBoardFragmentInteractionListener mListener, Context context) {
this.mValues = mValues;
this.mContext = context;
this.mListener = mListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_board, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int i) {
holder.mItem = mValues.get(i);
holder.tvName.setText(holder.mItem.getName());
holder.tvWaiter.setVisibility(View.GONE);
holder.tvCount.setVisibility(View.GONE);
final boolean[] clicked = {false};
GestureDetector gestureDetector;
byte[] decodedString = Base64.decode(holder.mItem.getSrc(), Base64.DEFAULT);
try {
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
holder.ivTable.setImageBitmap(decodedByte);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, String> map = isEmpty(holder.mItem.getAreaId(), holder.mItem.getName());
if (!map.isEmpty()) {
holder.ivTable.setImageResource(R.mipmap.ic_launcher_atento_round);
holder.tvWaiter.setText(map.get("name"));
holder.tvWaiter.setVisibility(View.VISIBLE);
holder.tvCount.setText("(" + map.get("count") + ")");
holder.tvCount.setVisibility(View.VISIBLE);
}
gestureDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener(){
});
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
if(!clicked[0]){
clicked[0] = true;
if (mListener != null) {
mListener.onClickBoard(mValues.get(i));
}else{
((MainActivity)mContext).onClickBoard(mValues.get(i).getAreaId(), mValues.get(i).getName());
}
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public void setmValues(List<Board> mValues) {
this.mValues = mValues;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
#BindView(R.id.ivBoard)
ImageView ivTable;
#BindView(R.id.tvName)
TextView tvName;
#BindView(R.id.tvWaiter)
TextView tvWaiter;
#BindView(R.id.tvCount)
TextView tvCount;
public Board mItem;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
this.mView = itemView;
}
#Override
public String toString() {
return "ViewHolder{" +
"mView=" + mView +
", ivTable=" + ivTable +
", tvName=" + tvName +
", tvWaiter=" + tvWaiter +
", tvCount=" + tvCount +
", mItem=" + mItem +
'}';
}
}
public Map<String, String> isEmpty(String area, String mesa) {
Map<String, String> response = new HashMap<>();
if (!mOcu.get(0).isEmpty()) {
for (int i = 0; i <= mOcu.get(0).size() - 1; i++) {
if (mOcu.get(0).get(i).trim().equals(area.trim()) && mesa.equals(mOcu.get(1).get(i))) {
Log.i("Mesa Ocupada", mOcu.get(0).get(i) + " -- " + mOcu.get(1).get(i));
response.put("code", mOcu.get(2).get(i));
response.put("name", mOcu.get(3).get(i));
response.put("count", mOcu.get(5).get(i));
return response;
}
}
}
return response;
}
}
Dialog Code:
public void dialogCustomer() {
View mView = getLayoutInflater().inflate(R.layout.dialog_customer, null);
final AlertDialog dialog = new AlertDialog.Builder(this).setView(mView).create();
final TextView tvCustomer = (TextView) mView.findViewById(R.id.tvCustomer);
final EditText etCustomer = (EditText) mView.findViewById(R.id.etCustomer);
final Button btnSubmit = (Button) mView.findViewById(R.id.btnSubmit);
tvCustomer.setText("Atento Cliente");
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startHomeActivity(etCustomer.getText().toString());
dialog.dismiss();
}
});
etCustomer.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
startHomeActivity(etCustomer.getText().toString());
dialog.dismiss();
return true;
}
return false;
}
});
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
orderFragment = (OrderFragment) getSupportFragmentManager().findFragmentByTag("orderFragment");
if (orderFragment == null) {
new AccessBoardAsyncTask(mContext).execute("L", mBoard);
}
}
});
dialog.show();
}
If you prefer fix it from your adapter, I think you could fix it declaring a private boolean disableViews = false; in your adapter, then call notifyDataSetChanged(); after user hits a holder.mView:
if (!disableViews) {
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
if (mListener != null) {
mListener.onClickBoard(mValues.get(i));
}else{
((MainActivity)mContext).onClickBoard(mValues.get(i).getAreaId(), mValues.get(i).getName());
}
disableViews = true;
notifyDataSetChanged();
}
});
} else {
holder.mView.setOnClickListener(null);
}
And then set disableViews = false; when you want to receive click events again.
Is it possible to expand and collapse multiple CardViews within a RecyclerView at the same time? I created a header (for my RecyclerView) with two buttons but I'm not sure what needs to go in the click event.
RecyclerView adapter class
public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
public boolean isSupposedToBeCollapsed;
private Context mContext;
RecyclerViewHeader header;
List<RecyclerViewItem> listItems;
ValueAnimator mAnimator;
public MyRecyclerAdapter(Context context, RecyclerViewHeader header, List<RecyclerViewItem> listItems)
{
this.mContext = context;
this.header = header;
this.listItems = listItems;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_header, parent, false);
return new MyRecyclerAdapter.VHHeader(v);
}
else if(viewType == TYPE_ITEM)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
return new MyRecyclerAdapter.VHItem(v);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
private RecyclerViewItem getItem(int position)
{
return listItems.get(position);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Typeface iconFont = FontManager.getTypeface(mContext, FontManager.FONTAWESOME);
if (holder instanceof VHHeader)
{
final VHHeader vhHeader = (VHHeader)holder;
vhHeader.btnExpandAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isSupposedToBeCollapsed){
// change visibility to 'VISIBLE'
txtB.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
// apply animation to the height of 'txtB'
mAnimator = slideAnimator(0, textBHeight);
// start the animation
mAnimator.start();
}
else{
}
}
});
vhHeader.btnCollapseAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isSupposedToBeCollapsed){
// change visibility to 'VISIBLE'
txtB.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
// apply animation to the height of 'txtB'
mAnimator = slideAnimator(0, textBHeight);
// start the animation
mAnimator.start();
}
else{
}
}
});
}
else if (holder instanceof VHItem)
{
RecyclerViewItem currentItem = getItem(position-1);
final VHItem vhItem = (VHItem)holder;
vhItem.txtA.setText(currentItem.getTitle());
vhItem.txtB.setText(currentItem.getDescription());
vhItem.txtB.setVisibility(View.GONE);
vhItem.txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
vhItem.txtExpandCollapse.setTypeface(iconFont);
//Add onPreDrawListener
vhItem.txtB.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
vhItem.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
vhItem.txtB.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
vhItem.txtB.measure(widthSpec, heightSpec);
vhItem.textBHeight = vhItem.txtB.getMeasuredHeight();
return true;
}
});
vhItem.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItem.txtB.getVisibility() == View.GONE){
vhItem.expand();
} else {
vhItem.collapse();
}
}
});
vhItem.mLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItem.txtB.getVisibility() == View.GONE){
vhItem.expand();
} else {
vhItem.collapse();
}
}
});
vhItem.txtExpandCollapse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItem.txtB.getVisibility() == View.GONE){
vhItem.expand();
} else {
vhItem.collapse();
}
}
});
}
}
// need to override this method
#Override
public int getItemViewType(int position) {
if(isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
private boolean isPositionHeader(int position)
{
return position == 0;
}
// increasing getItemcount to 1. This will be the row of header.
#Override
public int getItemCount() {
return listItems.size()+1;
}
class VHHeader extends RecyclerView.ViewHolder{
Button btnCollapseAll, btnExpandAll;
public VHHeader(View headerView) {
super(headerView);
this.btnCollapseAll = headerView.findViewById(R.id.btn_collapseall);
this.btnExpandAll = headerView.findViewById(R.id.btn_expandall);
}
}
public class VHItem extends RecyclerView.ViewHolder{
CardView cardView;
LinearLayout mLinearLayout;
RecyclerView mRecyclerView;
RelativeLayout mRelativeLayout;
TextView txtExpandCollapse, txtA, txtB;
public int textBHeight;
public VHItem(View itemView) {
super(itemView);
this.cardView = itemView.findViewById(R.id.cv);
this.mLinearLayout = itemView.findViewById(R.id.cardview_tconnections_titlerow);
this.mRelativeLayout = itemView.findViewById(R.id.my_relativelayout);
this.mRecyclerView = itemView.findViewById(R.id.my_recyclerview);
this.txtExpandCollapse = itemView.findViewById(R.id.tv_expandcollapse);
this.txtA = itemView.findViewById(R.id.tv_A);
this.txtB = itemView.findViewById(R.id.tv_B);
}
private void expand() {
// change visibility to 'VISIBLE'
txtB.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
// apply animation to the height of 'txtB'
mAnimator = slideAnimator(0, textBHeight);
// start the animation
mAnimator.start();
}
private void collapse() {
// change direction of chevron to 'down'
txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
int finalHeight = txtB.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
txtB.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
public ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// update height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = txtB.getLayoutParams();
layoutParams.height = value;
txtB.setLayoutParams(layoutParams);
}
});
return animator;
}
}
}
Fragment class
public class MyFragment extends android.support.v4.app.Fragment {
private MyRecyclerAdapter adapter;
public MyFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_rv, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
View v = getView();
assert v != null;
recyclerView = v.findViewById(R.id.my_recyclerview);
linearLayoutManager = new LinearLayoutManager(getActivity());
MyRecyclerAdapter adapter = new MyRecyclerAdapter(getContext(), getHeader(), getListItems());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
super.onActivityCreated(savedInstanceState);
}
RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager;
public RecyclerViewHeader getHeader()
{
return new RecyclerViewHeader();
}
public List<RecyclerViewItem> getListItems()
{
List<RecyclerViewItem> rvItems = new ArrayList<>();
RecyclerViewItem itemA = new RecyclerViewItem();
itemA.setConnectionMode("Item A");
itemA.setConnectionName("Feature A1");
rvItems.add(itemA);
RecyclerViewItem itemB = new RecyclerViewItem();
itemB.setConnectionMode("Item B");
itemB.setConnectionName("Feature B1\nFeature B2");
rvItems.add(itemB);
RecyclerViewItem itemC = new RecyclerViewItem();
itemC.setConnectionMode("Item C");
itemC.setConnectionName("Feature C1\nFeature C2\nFeature C3");
rvItems.add(itemC);
return rvItems;
}
}
What you can do is, set a variable(boolean) that stores the state of the card (expanded/collapsed) in the RecyclerAdapter code.
Then, in your onBindViewHolder code block, write a piece of code to check if the card should be expanded or collapsed using the above-mentioned variable and the required display code.
Example:
if(isSuppossedToBeCollapsed){
textView.setVisibility = false;
}
else{
textView.setVisibility = true;
}
You can then call notifyDatasetChanged in your RecyclerAdapter code to update the recycler views when you click the button which will redraw the views and reflect the state of the cards(expanded/collapsed) accordingly.
NotifyDatasetChanged Documentation
I'm trying to add an item on RecycleView like this:
I have an object called Image
public class Image{
public String name;
public String url;
}
When I click on the button to add a new item, my code is like this:
#Override
public void addItemOnList(String url) {
adapter.addItem(new ImageObject("aaaaaa", R.drawable.close_button));
}
That is my method which inserts on the list.
public void addItem(ImageObject imageObject) {
itemList.add(imageObject);
notifyDataSetChanged();
}
My problem is when I click for the first time in additem my onBindViewHolder doesn't iterate all the list but when I check in debug mod my getItemCount is correct! So If I try to add an item after the first time all work well.
MainActivity
public class MainActivity extends AppCompatActivity implements RecyclerViewClickListener, OnStartDragListener {
private RecyclerViewAdapter adapter;
private ArrayList<ImageObject> listViewItems;
private RecyclerView recyclerView;
private ItemTouchHelper itemTouchHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
StaggeredGridLayoutManager staggeredLayoutManager = new StaggeredGridLayoutManager(3, 1);
recyclerView.setLayoutManager(staggeredLayoutManager);
List<ImageObject> staggered = getListItemData();
adapter = new RecyclerViewAdapter(this, staggered);
recyclerView.setAdapter(adapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
private List<ImageObject> getListItemData() {
listViewItems = new ArrayList<ImageObject>();
listViewItems.add(new ImageObject("Alkane", R.drawable.one));
listViewItems.add(new ImageObject("Ethane", R.drawable.two));
listViewItems.add(new ImageObject("Alkyne", R.drawable.three));
listViewItems.add(new ImageObject("Benzene", R.drawable.four));
listViewItems.add(new ImageObject("Alkane", R.drawable.one));
listViewItems.add(new ImageObject("Ethane", R.drawable.two));
listViewItems.add(new ImageObject("Alkyne", R.drawable.three));
listViewItems.add(new ImageObject("Benzene", R.drawable.four));
listViewItems.add(new ImageObject("Alkane", R.drawable.one));
listViewItems.add(new ImageObject("Ethane", R.drawable.two));
listViewItems.add(new ImageObject("Alkyne", R.drawable.three));
listViewItems.add(new ImageObject("Benzene", R.drawable.four));
return listViewItems;
}
#Override
public void addButtonClicked() {
FragmentManager fm = getSupportFragmentManager();
AlertFragment.newInstance(this).show(fm, "dialog");
}
#Override
public void addItemOnList(String url) {
adapter.addItem(new ImageObject("aaaaaa", R.drawable.close_button));
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
itemTouchHelper.startDrag(viewHolder);
}
}
My Adapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolders> implements ItemTouchHelperAdapter {
private List<ImageObject> itemList;
private MainActivity mainActivity;
private RecyclerViewClickListener recycleListener;
private OnStartDragListener dragStartListener;
public RecyclerViewAdapter(MainActivity mainActivity, List<ImageObject> itemList) {
this.itemList = itemList;
this.mainActivity = mainActivity;
this.recycleListener = mainActivity;
this.dragStartListener = mainActivity;
}
#Override
public ViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView;
switch (viewType) {
case 1:
layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.add_item_list, null);
break;
default:
layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, null);
break;
}
return new ViewHolders(layoutView);
}
#Override
public void onBindViewHolder(final ViewHolders holder, final int position) {
switch (holder.getItemViewType()) {
case 1:
configureViewHolderAddItem(holder, position);
break;
case 0:
configureDefaultViewHolder(holder, position);
break;
}
}
private void configureViewHolderAddItem(final ViewHolders holder, final int position) {
holder.addItemLayout = holder.itemView.findViewById(R.id.add_item_layout);
holder.addItemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
recycleListener.addButtonClicked();
}
});
}
private void configureDefaultViewHolder(final ViewHolders holder, final int position) {
Log.e("test", "position - " + position);
Log.e("test", "name - " + itemList.get(position).getName());
holder.itemLayout = holder.itemView.findViewById(R.id.main_layout);
holder.removeItemButton = holder.itemView.findViewById(R.id.remove_item_button);
holder.itemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
itemList.remove(holder.getLayoutPosition());
notifyItemRemoved(holder.getLayoutPosition());
notifyItemRangeChanged(holder.getLayoutPosition(), itemList.size());
}
});
holder.itemLayout.setBackgroundResource(itemList.get(position).getPhoto());
holder.itemLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
dragStartListener.onStartDrag(holder);
}
return false;
}
});
//resizeTheFirstPosition(holder, position);
}
private void resizeTheFirstPosition(ViewHolders holder, int position) {
if (position == 0) {
int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
200, mainActivity.getResources().getDisplayMetrics());
holder.itemLayout.getLayoutParams().height = dimensionInDp;
holder.itemLayout.getLayoutParams().width = dimensionInDp;
holder.itemLayout.requestLayout();
}
}
public void addItem(ImageObject imageObject) {
itemList.add(imageObject);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return position == itemList.size() - 1 ? 1 : 0;
}
#Override
public int getItemCount() {
return this.itemList.size();
}
#Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(itemList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
#Override
public void onItemDismiss(int position) {
itemList.remove(position);
notifyItemRemoved(position);
}
public class ViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener,
ItemTouchHelperViewHolder {
private ImageView removeItemButton;
private ImageView addItemButton;
private FrameLayout addItemLayout;
private RelativeLayout itemLayout;
public ViewHolders(View itemView) {
super(itemView);
}
#Override
public void onClick(View view) {
itemList.remove(getLayoutPosition());
//notifyItemRemoved(getLayoutPosition());
notifyItemRangeChanged(getLayoutPosition(), itemList.size());
Toast.makeText(mainActivity, "Removed item- " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
}
#Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
#Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
}
Finally, I fixed this. I don't know why but I change how I insert on the list
Old code:
public void addItem(ImageObject imageObject) {
itemList.add(imageObject);
notifyDataSetChanged();
}
New code:
public void addItem(ImageObject imageObject) {
itemList.add(itemList.size() - 1, imageObject);
notifyDataSetChanged();
}
//I have recycler view as follows
private void prepareGridRecycleView() {
gridRecyclerView.setHasFixedSize(true);
SpaceItemGridDecoration itemDecoration = new SpaceItemGridDecoration(10);
gridRecyclerView.setClipToPadding(false);
gridRecyclerView.addItemDecoration(itemDecoration);
adapter = new ShopPageGridViewAdapter(ShopPageContent.this, new ShopPageHeaderGridInterface() {
#Override
public void onClick(boolean isClicked) {
gridRecyclerView.setVisibility(View.INVISIBLE);
listRecycleView.setVisibility(View.VISIBLE);
}
}, new ShopPageHeaderListInterface() {
#Override
public void onClick(boolean isClicked) {
}
}, new CartCoordivateInfoHolder() {
#Override
public void setViewCoordinate(ImageView view, int x, int y) {
view.setVisibility(View.VISIBLE);
int pos[] = new int[2];
cart.getLocationOnScreen(pos);
Log.e("x", String.valueOf(pos[0]));
Log.e("y", String.valueOf(pos[1]));
view.bringToFront();
Animations anim = new Animations();
Animation a = anim.fromAtoB(20, 30, 6000,6000,null,850);
a.setFillAfter(true);
view.setAnimation(a);
a.startNow();
}
}, new ShopPageHeaderHelpInterface() {
#Override
public void onClick(boolean isClicked) {
AlertDialog.Builder builder = new AlertDialog.Builder(ShopPageContent.this);
View view = getLayoutInflater().inflate(R.layout.help_dialog, null);
builder.setView(view);
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.setCanceledOnTouchOutside(true);
}
}, new ShopPageHeaderFilterInterface() {
#Override
public void onClick(boolean isClick) {
AlertDialog.Builder builder = new AlertDialog.Builder(ShopPageContent.this);
View view = getLayoutInflater().inflate(R.layout.filter_dialog, null);
LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.circle_view_child);
RangeSeekbar seekBar = (RangeSeekbar) view.findViewById(R.id.seekbar);
seekBar.setTextMarkSize(0);
prepareCircleImage(linearLayout);
final TextView s = (TextView) view.findViewById(R.id.s);
final TextView m = (TextView) view.findViewById(R.id.m);
final TextView l = (TextView) view.findViewById(R.id.l);
final TextView xl = (TextView) view.findViewById(R.id.xl);
final TextView xxl = (TextView) view.findViewById(R.id.xxl);
final TextView xxxl = (TextView) view.findViewById(R.id.xxxl);
s.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(s);
}
});
l.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(l);
}
});
m.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(m);
}
});
xl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(xl);
}
});
xxl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(xxl);
}
});
xxxl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setBackground(xxxl);
}
});
builder.setView(view);
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.setCanceledOnTouchOutside(true);
}
});
final GridLayoutManager manager = new GridLayoutManager(this, 2);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return adapter.isPositionHeader(position) ? manager.getSpanCount() : 1;
}
});
gridRecyclerView.setAdapter(adapter);
gridRecyclerView.setLayoutManager(manager);
}
//the recycler view adapter seems as follows
public class ShopPageGridViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private List<String> list = new ArrayList<>();
private Context context;
private ShopPageHeaderGridInterface shopPageHeaderGridInterface;
private ShopPageHeaderListInterface shopPageHeaderListInterface;
private ShopPageHeaderFilterInterface shopPageHeaderFilterInterface;
private CartCoordivateInfoHolder cartCoordivateInfoHolder;
private ShopPageHeaderHelpInterface shopPageHeaderHelpInterface;
public ShopPageGridViewAdapter(Context context, ShopPageHeaderGridInterface shopPageHeaderGridInterface, ShopPageHeaderListInterface shopPageHeaderListInterface, CartCoordivateInfoHolder cartCoordivateInfoHolder, ShopPageHeaderHelpInterface shopPageHeaderHelpInterface, ShopPageHeaderFilterInterface shopPageHeaderFilterInterface) {
this.context = context;
this.shopPageHeaderGridInterface = shopPageHeaderGridInterface;
this.shopPageHeaderListInterface = shopPageHeaderListInterface;
this.cartCoordivateInfoHolder = cartCoordivateInfoHolder;
this.shopPageHeaderHelpInterface = shopPageHeaderHelpInterface;
this.shopPageHeaderFilterInterface = shopPageHeaderFilterInterface;
for (int i = 0; i <= 10; i++) {
list.add("hello");
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.shop_page_grid_layout_header, parent, false);
final ImageView heroImageView = (ImageView) v.findViewById(R.id.heroImageView);
heroImageView.post(new Runnable() {
#Override
public void run() {
heroImageView.getLayoutParams().height = (int) (heroImageView.getWidth() * 0.63);
}
});
final ImageView stackImage = (ImageView) v.findViewById(R.id.stack_image);
ImageView helpImage = (ImageView) v.findViewById(R.id.help);
final ImageView filterImage = (ImageView) v.findViewById(R.id.filter_image);
stackImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
shopPageHeaderGridInterface.onClick(true);
}
});
final ImageView gridImage = (ImageView) v.findViewById(R.id.grid_image);
gridImage.post(new Runnable() {
#Override
public void run() {
gridImage.getLayoutParams().height = (int) (gridImage.getHeight() * 0.80);
gridImage.getLayoutParams().width = (int) (gridImage.getWidth() * 0.80);
stackImage.getLayoutParams().height = (int) (stackImage.getHeight() * 0.80);
stackImage.getLayoutParams().width = (int) (stackImage.getWidth() * 0.80);
filterImage.getLayoutParams().height = (int) (filterImage.getHeight() * 0.80);
filterImage.getLayoutParams().width = (int) (filterImage.getWidth() * 0.80);
}
});
gridImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
shopPageHeaderListInterface.onClick(true);
}
});
helpImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
shopPageHeaderHelpInterface.onClick(true);
}
});
filterImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
shopPageHeaderFilterInterface.onClick(true);
}
});
return new VHHeader(v);
} else if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.shop_page_grid_layout, parent, false);
final RelativeLayout relativeLayout = (RelativeLayout) v.findViewById(R.id.grid_parent);
final ImageView gridItemImage=(ImageView)v.findViewById(R.id.grid_item_image);
new Handler().post(new Runnable() {
#Override
public void run() {
relativeLayout.getLayoutParams().height = (int) (relativeLayout.getWidth() * 1.2);
relativeLayout.requestLayout();
gridItemImage.setImageResource(R.drawable.winter_sale);
}
});
final ImageView cart = (ImageView) v.findViewById(R.id.cart);
final ImageView cartNumber = (ImageView) v.findViewById(R.id.cart_number);
cart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos[] = new int[2];
cartNumber.getLocationOnScreen(pos);
Log.e("x", String.valueOf(pos[0]));
Log.e("y", String.valueOf(pos[1]));
cartCoordivateInfoHolder.setViewCoordinate(cartNumber, pos[0], pos[1]);
}
});
return new VHItem(v);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof VHHeader) {
VHHeader VHheader = (VHHeader) holder;
} else if (holder instanceof VHItem) {
VHItem VHitem = (VHItem) holder;
}
}
// need to override this method
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
public boolean isPositionHeader(int position) {
return position == 0;
}
//increasing getItemcount to 1. This will be the row of header.
#Override
public int getItemCount() {
return list.size() + 1;
}
class VHHeader extends RecyclerView.ViewHolder {
public VHHeader(View itemView) {
super(itemView);
}
}
class VHItem extends RecyclerView.ViewHolder {
public VHItem(View itemView) {
super(itemView);
}
}
}
//So the problem I am facing is I have cart image in recycler view item and when clicked the cart image should translate to the cart icon at toolbar.But when clicked in recycler view ,item at the cart moves around in item and not comes outside of recycler view..
Well you can achieve this in many ways but i think sharedElementTransition will just do the thing for you
Use SharedElementTransition which make it easier as all the thing will be done by the android system itself you can reffer SharedElementTransition
Hope it Helped :)