I want to add the extra TextView
to the item of the RecyclerView.Adapter
based on the ModalObject sent to the RecyclerView.Adapter
Example:
I had a modal object with isAddText
variable. In onCreateViewHolder
will create the Holder Object with sending the itemView
as an parameter.
@Override public SolventViewHolders onCreateViewHolder(ViewGroup parent, int viewType) { View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.solvent_list, null); SolventViewHolders rcv = new SolventViewHolders(layoutView); return rcv; }
SolventViewHolders.java
public SolventViewHolders(View itemView) { super(itemView); itemView.setOnClickListener(this); textView = (TextView) itemView.findViewById(R.id.country_name); imageView = (ImageView) itemView.findViewById(R.id.country_photo); // Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. }
Dynamic RecyclerView With Non-Defined Data Structure (From Unknown CSV Data Structure) RecyclerView makes it easy to efficiently display large sets of data. You supply the data and define how each item looks, and the RecyclerView library dynamically creates the elements when they're needed.
A ViewHolder describes an item view and metadata about its place within the RecyclerView. RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive View. findViewById(int) results.
notifyDataSetChanged. Notify any registered observers that the data set has changed. There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred.
Normally, you would need to execute itemView.addView(view, layoutParams) to add another view programatically to your layout, but thing with ViewHolders is, they will be reused by RecyclerView to bind different items from the adapter, so you can't do that or this new TextView you wish to add will appear when another item is bound to this viewHolder instance again.
I can think of a few ways you can achieve your goal:
The first way is to add this textView to your layout and have its visibility by GONE by default, and set it to VISIBLE when binding that one item you need this TextView for, such as:
@Override public void onBindViewHolder(AbstractViewHolder holder, int position) { holder.extraTextView.setVisibility(View.GONE); if(shouldShowExtraTextView) { holder.extraTextView.setVisibility(View.VISIBLE); holder.extraTextView.setText(/* your text */); } // proceed to bind item to holder }
The second way is more elegant, it involves creating different ViewHolder type. First you need to create int constants for the two types of view to be shown by RecyclerView. Place in your adapter the following code:
private static final int VIEW_ORDINARY = 0; private static final int VIEW_WITH_EXTRA_TEXT_VIEW = 1;
Then implement the getItemViewType(int position) method of the adapter:
@Override public int getItemViewType(int position) { if(position == /* position of item that needs extra text view */) { return VIEW_WITH_EXTRA_TEXT_VIEW; } else { return VIEW_ORDINARY; } }
Next step is to create different Holder depending on returned type:
@Override public SolventViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType == VIEW_WITH_EXTRA_TEXT_VIEW) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.solvent_list_with_extra_text_view, parent, false); return new SolventViewHolderWithExtraTextView(itemView); } else { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.solvent_list, parent, false); return new SolventViewHolder(itemView); } }
Of course you need to define SolventViewHolderWithExtraTextView:
class SolventViewHolderWithExtraTextView extends SolventViewHolder { TextView extraTextView; public SolventViewHolderWithExtraTextView(View itemView) { super(itemView); this.extraTextView = (TextView) findViewById(R.id.extra_text_view); } }
And then in onBindViewHolder():
@Override public void onBindViewHolder(SolventViewHolder holder, int position) { // you can use inheritance to handle binding logic or check the item view type again: // bind ordinary view if(getItemViewType(position)) { // bind the extra textView ((SolventViewHolderWithExtraTextView)holder).extraTextView.setText("I hope this works"); } }
This way you have another type of ViewHolder for your items that need another TextView, and it will be reused within that category. It's a preferred way to do what you want to.
Another answer (which is really ugly solution if you ask me) is to add and remove view dynamically, such as:
@Override public void onBindViewHolder(AbstractViewHolder holder, int position) { if(shouldDisplayExtraTextView) { if(!holder.displaysExtraTextView() { holder.addExtraTextView(); } holder.extraTextView.setText("This solution is really ugly"); } else { if(holder.displaysExtraTextView() { holder.removeExtraTextView(); } } } class SolventViewHolders extends RecyclerView.ViewHolder { TextView extraTextView; boolean viewAdded = false; public SolventViewHolders(View itemView) { super(itemView); itemView.setOnClickListener(this); textView = (TextView) itemView.findViewById(R.id.country_name); imageView = (ImageView) itemView.findViewById(R.id.country_photo); // Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. extraTextView = new TextView(); } public void addExtraTextView() { ((ViewGroup)itemView).addView(extraTextView, layoutParams); viewAdded = true; } public void removeExtraTextView() { ((ViewGroup)itemView).removeView(extraTextView); viewAdded = false; } public boolean displaysExtraTextView() { return viewAdded; }
This is really ugly, because to add view to itemView you need to cast it to ViewGroup (which it doesn't have to be), so ensure that it always will be a ViewGroup or its subclass. Also, you need to provide proper layoutParams to add the extraTextView to itemView.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With