How to hide an item from Recycler View on a particular condition? - android

I am using Firebase Recycler Adapter (Firebase UI Library) to populate Recycler View. I want to hide an item(row) on a condition.
I have a LinearLayout containing a recycler view.
I set linear layout visibility to Gone in populateViewHolder() method of recycler view adapter.
#Override
protected void populateViewHolder(UsersViewHolder viewHolder, User user, int position) {
if (user.getUserEmail().equals(Utils.decodeEmail(userEmail))) {
viewHolder.llMain.setVisibility(View.GONE);
return;
}
viewHolder.tvUserEmail.setText(user.getUserEmail());
}
It hides the LinearLayout but the row remains there with empty space.
Is there any method I should override to overcome this or is there any way to achieve the result?

In some cases changing only visibility attribute might still end up as allocated blank space (because of parent view's padding, margins, inner elements etc). Then changing height of the parent view helps:
holder.itemView.setVisibility(View.GONE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
Then be sure that in the condition that it should be visible, also set:
holder.itemView.setVisibility(View.VISIBLE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
You need to do that because the viewHolder is recycled as you scroll, if you change properties as this and never return them to their natural state, other elements will be already hidden in the event they reuse the same view.

You should hide all views or parent from UsersViewholder layout xml.
You should hide entire viewholder or each view
Entire viewholder:
itemView.setVisibility(View.GONE);
or each element:
view.setVisibility(View.GONE);
But don't forget to set them VISIBLE otherwise, you will end up with some strange things from recycling

IF
view.setVisibility(View.GONE);
gives you a Blank view
Then follow This.
public static class Data_ViewHolder extends RecyclerView.ViewHolder {
private final LinearLayout layout;
final LinearLayout.LayoutParams params;
public Show_Chat_ViewHolder(final View itemView) {
super(itemView);
.
.
.
layout =(LinearLayout)itemView.findViewById(R.id.show_item_layout);
params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
.
.
.
}
private void Layout_hide() {
params.height = 0;
//itemView.setLayoutParams(params); //This One.
layout.setLayoutParams(params); //Or This one.
}
}
Now Call from Adapter
mFirebaseAdapter = new FirebaseRecyclerAdapte......{
public void populateViewHolder.....{
if(model.getData().equals("..Something.."))
{
viewHolder.Layout_hide();
}
else
viewHolder.Person_Email(model.getEmail());
}
}

If you are hiding whole itemView and facing the problem of blank spaces.
Try this to hide the itemView.
holder.itemView.setVisibility(View.GONE);
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = 0;
params.width = 0;
holder.itemView.setLayoutParams(params);
And this to show it.
holder.itemView.setVisibility(View.VISIBLE);
This is a recyclerView, so use both in if else block or you might encounter some unintended UI issues.

There is no built in way to hide a child in RecyclerView.
But you can implement this feature in your Adapter.
public class MyAdapter extends RecyclerView.Adapter<...>{
List<Object> items;
Map<Integer,Object> deletedItems;
...
public void hideItem(final int position) {
deletedItems.add(position, items.get(position));
items.remove(position);
notifyItemRemoved(position);
}
....
}

"GONE" will not remove the space occupied by the item ....you can use
if (condition) {
item.layoutParams.height = 0
item.layoutParams.width = 0
}
inside "onBindViewHolder"

public class OfferViewHolder extends RecyclerView.ViewHolder {
public TextView textViewOfferName;
public LabelImageView labelImageView;
public TextView textViewOldPrice;
public TextView textViewNewPrice;
public TextView textViewShopName;
public TextView textViewTimeDate;
public TextView textViewDistance;
public LinearLayout linearLayoutMain;
public OfferViewHolder(View view) {
super(view);
linearLayoutMain=(LinearLayout) view.findViewById(R.id.ll_main);
textViewOfferName = (TextView) view.findViewById(R.id.textViewoffername);
labelImageView=(LabelImageView) view.findViewById(R.id.labelImageView) ;
textViewOldPrice=(TextView) view.findViewById(R.id.textViewOldPrice);
textViewNewPrice=(TextView) view.findViewById(R.id.textViewNewPrice);
textViewShopName=(TextView) view.findViewById(R.id.textViewShopName);
textViewTimeDate=(TextView) view.findViewById(R.id.textViewDate);
textViewDistance=(TextView) view.findViewById(R.id.textViewDistance);
linearLayoutMain.setVisibility(View.GONE);
textViewOfferName.setVisibility(View.GONE);
labelImageView.setVisibility(View.GONE);
textViewOldPrice.setVisibility(View.GONE);
textViewNewPrice.setVisibility(View.GONE);
textViewShopName.setVisibility(View.GONE);
textViewTimeDate.setVisibility(View.GONE);
textViewDistance.setVisibility(View.GONE);
}
}`enter code here`
THEN IN YOUR ADAPTER
if (a.equals(offer.getOfferCategory())) {
if (offer.getOfferCategory()==null){
// chatMessageViewHolder.getLinearLayoutMain().setVisibility(View.GONE);
// chatMessageViewHolder.linearLayoutMain.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}
else {
chatMessageViewHolder.itemView.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewShopName.setText(offer.getOfferCategory());
chatMessageViewHolder.linearLayoutMain.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewOfferName.setVisibility(View.VISIBLE);
chatMessageViewHolder.labelImageView.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewOldPrice.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewNewPrice.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewShopName.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewTimeDate.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewDistance.setVisibility(View.VISIBLE);
}
Thank you lorescu George Cătălin and Dhalav

holder.itemView.setVisibility(View.VISIBLE); is not working now. I am using this
holder.itemView.findViewById(R.id.card).setVisibility(View.GONE);
you can easily send the ViewHolder value to your action function ..

I do not recommend answers with setting height and width of View to 0 because adapter still needs to render them and if there are too many hidden items this can cause lags, it is better to change the list itself and then send it to the adapter

It seems like RV internally caches root view info so changing it's visibility does nothing to occuppied space by the item.
Wrap you RV item view with FrameLayout and set View.GONE to inner view. This way occupped space will be cleared correctly as well as item won't be shown at all.

private fun hideShowItemView(itemView: View, toShow: Boolean) {
itemView.isVisible = toShow
itemView.layoutParams.height = if (toShow) ViewGroup.LayoutParams.WRAP_CONTENT else 0
}
itemView is an ItemView of the ViewHolder
toShow is a boolean to hide or show item of recyclerview
Use below line of code in onBindViewHolder block as per the requirement,
To hide Item : hideShowItemView(holder.itemView, false)
To show Item : hideShowItemView(holder.itemView, true)

Related

Filtering Firebase data in adapter leaves empty space [duplicate]

I am using Firebase Recycler Adapter (Firebase UI Library) to populate Recycler View. I want to hide an item(row) on a condition.
I have a LinearLayout containing a recycler view.
I set linear layout visibility to Gone in populateViewHolder() method of recycler view adapter.
#Override
protected void populateViewHolder(UsersViewHolder viewHolder, User user, int position) {
if (user.getUserEmail().equals(Utils.decodeEmail(userEmail))) {
viewHolder.llMain.setVisibility(View.GONE);
return;
}
viewHolder.tvUserEmail.setText(user.getUserEmail());
}
It hides the LinearLayout but the row remains there with empty space.
Is there any method I should override to overcome this or is there any way to achieve the result?
In some cases changing only visibility attribute might still end up as allocated blank space (because of parent view's padding, margins, inner elements etc). Then changing height of the parent view helps:
holder.itemView.setVisibility(View.GONE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
Then be sure that in the condition that it should be visible, also set:
holder.itemView.setVisibility(View.VISIBLE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
You need to do that because the viewHolder is recycled as you scroll, if you change properties as this and never return them to their natural state, other elements will be already hidden in the event they reuse the same view.
You should hide all views or parent from UsersViewholder layout xml.
You should hide entire viewholder or each view
Entire viewholder:
itemView.setVisibility(View.GONE);
or each element:
view.setVisibility(View.GONE);
But don't forget to set them VISIBLE otherwise, you will end up with some strange things from recycling
IF
view.setVisibility(View.GONE);
gives you a Blank view
Then follow This.
public static class Data_ViewHolder extends RecyclerView.ViewHolder {
private final LinearLayout layout;
final LinearLayout.LayoutParams params;
public Show_Chat_ViewHolder(final View itemView) {
super(itemView);
.
.
.
layout =(LinearLayout)itemView.findViewById(R.id.show_item_layout);
params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
.
.
.
}
private void Layout_hide() {
params.height = 0;
//itemView.setLayoutParams(params); //This One.
layout.setLayoutParams(params); //Or This one.
}
}
Now Call from Adapter
mFirebaseAdapter = new FirebaseRecyclerAdapte......{
public void populateViewHolder.....{
if(model.getData().equals("..Something.."))
{
viewHolder.Layout_hide();
}
else
viewHolder.Person_Email(model.getEmail());
}
}
If you are hiding whole itemView and facing the problem of blank spaces.
Try this to hide the itemView.
holder.itemView.setVisibility(View.GONE);
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = 0;
params.width = 0;
holder.itemView.setLayoutParams(params);
And this to show it.
holder.itemView.setVisibility(View.VISIBLE);
This is a recyclerView, so use both in if else block or you might encounter some unintended UI issues.
There is no built in way to hide a child in RecyclerView.
But you can implement this feature in your Adapter.
public class MyAdapter extends RecyclerView.Adapter<...>{
List<Object> items;
Map<Integer,Object> deletedItems;
...
public void hideItem(final int position) {
deletedItems.add(position, items.get(position));
items.remove(position);
notifyItemRemoved(position);
}
....
}
"GONE" will not remove the space occupied by the item ....you can use
if (condition) {
item.layoutParams.height = 0
item.layoutParams.width = 0
}
inside "onBindViewHolder"
public class OfferViewHolder extends RecyclerView.ViewHolder {
public TextView textViewOfferName;
public LabelImageView labelImageView;
public TextView textViewOldPrice;
public TextView textViewNewPrice;
public TextView textViewShopName;
public TextView textViewTimeDate;
public TextView textViewDistance;
public LinearLayout linearLayoutMain;
public OfferViewHolder(View view) {
super(view);
linearLayoutMain=(LinearLayout) view.findViewById(R.id.ll_main);
textViewOfferName = (TextView) view.findViewById(R.id.textViewoffername);
labelImageView=(LabelImageView) view.findViewById(R.id.labelImageView) ;
textViewOldPrice=(TextView) view.findViewById(R.id.textViewOldPrice);
textViewNewPrice=(TextView) view.findViewById(R.id.textViewNewPrice);
textViewShopName=(TextView) view.findViewById(R.id.textViewShopName);
textViewTimeDate=(TextView) view.findViewById(R.id.textViewDate);
textViewDistance=(TextView) view.findViewById(R.id.textViewDistance);
linearLayoutMain.setVisibility(View.GONE);
textViewOfferName.setVisibility(View.GONE);
labelImageView.setVisibility(View.GONE);
textViewOldPrice.setVisibility(View.GONE);
textViewNewPrice.setVisibility(View.GONE);
textViewShopName.setVisibility(View.GONE);
textViewTimeDate.setVisibility(View.GONE);
textViewDistance.setVisibility(View.GONE);
}
}`enter code here`
THEN IN YOUR ADAPTER
if (a.equals(offer.getOfferCategory())) {
if (offer.getOfferCategory()==null){
// chatMessageViewHolder.getLinearLayoutMain().setVisibility(View.GONE);
// chatMessageViewHolder.linearLayoutMain.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}
else {
chatMessageViewHolder.itemView.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewShopName.setText(offer.getOfferCategory());
chatMessageViewHolder.linearLayoutMain.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewOfferName.setVisibility(View.VISIBLE);
chatMessageViewHolder.labelImageView.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewOldPrice.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewNewPrice.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewShopName.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewTimeDate.setVisibility(View.VISIBLE);
chatMessageViewHolder.textViewDistance.setVisibility(View.VISIBLE);
}
Thank you lorescu George Cătălin and Dhalav
holder.itemView.setVisibility(View.VISIBLE); is not working now. I am using this
holder.itemView.findViewById(R.id.card).setVisibility(View.GONE);
you can easily send the ViewHolder value to your action function ..
I do not recommend answers with setting height and width of View to 0 because adapter still needs to render them and if there are too many hidden items this can cause lags, it is better to change the list itself and then send it to the adapter
It seems like RV internally caches root view info so changing it's visibility does nothing to occuppied space by the item.
Wrap you RV item view with FrameLayout and set View.GONE to inner view. This way occupped space will be cleared correctly as well as item won't be shown at all.
private fun hideShowItemView(itemView: View, toShow: Boolean) {
itemView.isVisible = toShow
itemView.layoutParams.height = if (toShow) ViewGroup.LayoutParams.WRAP_CONTENT else 0
}
itemView is an ItemView of the ViewHolder
toShow is a boolean to hide or show item of recyclerview
Use below line of code in onBindViewHolder block as per the requirement,
To hide Item : hideShowItemView(holder.itemView, false)
To show Item : hideShowItemView(holder.itemView, true)

How to make a set of views invisible in android

I'm trying to make a set of views (that include several textviews and buttons - all in different parent layouts, but in the same activity) invisible if a particular condition is evaluated to false.
The conventional way to do that would be:
findViewById(R.id.myview).setVisibility(View.INVISIBLE);
My question is, will I have to do this for all the views one by one that I want to be invisible, And then toggle them back when I want them visible?
Or, is there a way to avoid the code-repetition?
If the Views are in different parents , you can't do it directly, but you can implement a method to change the visibility of a bunch of Views if you want to keep your code clean:
List<View> relatedViews = new ArrayList<>();
// ...
relatedViews.add(view1);
relatedViews.add(view2);
relatedViews.add(view3);
// ...
changeVisibility(relatedViews, View.INVISIBLE);
// ...
private void changeVisibility(List<View> views, int visibility) {
for (View view : views) {
view.setVisibility(visibility);
}
}
As a side note, you may want to change the visibility to View.GONE instead of View.INVISIBLE so it doesn't take any space in the layout.
you can use something like this. It's not the most elegant solution but works.
The idea is give to each view that you want to hide a same content description, because in the same layout you can not use same id for multiple view. With the same content description you can find all views in your layout and hide them.
That's an example considering the first layout as Linear. You can change obviously ;)
public class TestActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
LinearLayout rootLayout = (LinearLayout)findViewById(R.id.rootLayout);
int childcount = rootLayout.getChildCount();
for (int i=0; i < childcount; i++){
View v = rootLayout.getChildAt(i);
if(v.getContentDescription() != null && v.getContentDescription().equals("invisibleView")){
v.setVisibility(View.INVISIBLE);
//I suggest you to use GONE instead of INVISIBLE to remove the space of the view
}
}
}
}
in your xml give to the object that you want to hide this property
android:contentDescription="invisibleView"
Use varargs method for show or hide multiple views.
for example if you have views like view1, view2.....etc
then just call setVisibility(View.VISIBLE,view1,view2)
public static void setVisibility(int visibility, View... views){
for (View view : views){
view.setVisibility(visibility);
}
}

RecycleView adapter data show wrong when scrolling too fast

I have a custom Recycle View adapter that list my items. in each Item I check database and draw some circles with colors.
when I scroll listview very fast every drawed data ( not title and texts) show wrongs!
how I can manage dynamic View creation without showing wrong data?!
#Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) {
itemViewHolder.date.setText(items.get(i).getData()); // set the title
itemViewHolder.relative_layout_tag_place.addView(generateTagImages(items.get(i).getServerId())); // had to generate a Relativelaout with
}
and this is importMenuTags():
private RelativeLayout generateTagImages(String serverId) {
List<String> color_list = new ArrayList<>();
RelativeLayout result = new RelativeLayout(context);
List<String> list = db.getCardTags(serverId);
int i = 0;
for (String string : list) {
RelativeLayout rl = new RelativeLayout(context);
color_list.add(get_the_proper_color);
Drawable drawable = context.getResources().getDrawable(R.drawable.color_shape);
drawable.setColorFilter(Color.parseColor(dao.getTagColor(string)), PorterDuff.Mode.SRC_ATOP);
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lparams.addRule(RelativeLayout.ALIGN_PARENT_START);
lparams.setMargins(i, 0, 0, 0);
lparams.width = 35;
lparams.height = 35;
rl.setLayoutParams(lparams);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
rl.setBackground(drawable);
} else {
rl.setBackgroundDrawable(drawable);
}
result.addView(rl);
i = i + 25;
}
return result;
}
I also had the same problem in simple custom adapter that it's solved by moving my function place out of
if (convertView == null) {
this is the link.
As per seeing in your code, I found your relative layout must be showing some extra data while scrolling. And thats because of recycling of views. Here
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) {
itemViewHolder.date.setText(items.get(i).getData()); // set the title
itemViewHolder.relative_layout_tag_place.addView(generateTagImages(items.get(i).getServerId())); // had to generate a Relativelaout with
//Problem is here.
Suppose you added some child views in above holde.relative_layout , and this ViewHodler is recyclerd and provided to another item view, It already have all previously added views in it. and you are adding new child view with them. Hope you understand your problem.
Solution: Very easy one. remove all previsousley added view in onBindViewHolder
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) {
itemViewHolder.date.setText(items.get(i).getData()); // set the title
itemViewHolder.relative_layout_tag_place.removeAllViews();
itemViewHolder.relative_layout_tag_place.addView(generateTagImages(items.get(i).getServerId())); // had to generate a Relativelaout with
I was found this solution after 3 day...hope it will work for you.
I had the same problem and the only solution I found for this is:
holder.setIsRecyclable(false);
Your recycler will not recycle anymore so the items will be the same when you scroll, and if you want to delete some item do not use notifyitemRemoved(position), use notifyDataSetChanged() instead.

Implement Google+ card liked animation via RecylerView

Previously, I implemented Google+ card liked animation (Video), by using technique mentioned in New Google Now and Google+ card interface
Override LinearLayout's onGlobalLayout to start animation, so that when activity first launched, we can see the slide up animation of cards.
Override ScrollView's onScrollChanged to start animation, so that during scrolling, we can see the newly visible cards being animated.
So far, I don't see any technique from RecylerView's example.
I was wondering, without using LinearLayout and ScrollView, can with achieve the same outcome, by using RecylerView? Is there any code example available? (So far, I unable to find one yet)
Add these lines in RecyclerView 's adaptor. Make a Variable for Each card i.e(convertView) here and initialise it.
int mLastPosition = 0;
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView card_head, card_body;
View convertView;
#SuppressLint("NewApi")
public ViewHolder(View v) {
super(v);
convertView = v;
}
}
Bind you view by position
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// do your thing here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
float initialTranslation = (mLastPosition <= position ? 150f
: -150f);
holder.convertView.setTranslationY(initialTranslation);
holder.convertView.animate()
.setInterpolator(new DecelerateInterpolator(1.0f))
.translationY(0f).setDuration(900l).setListener(null);
}
// Keep track of the last position we loaded
mLastPosition = position;
}
here , you have to animate the who view it calls onBindViewHolder method when new card is created animate the whole view customize it.

Hiding views in RecyclerView

I have code like this
public static class MyViewHolder extends RecyclerView.ViewHolder {
#InjectView(R.id.text)
TextView label;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
public void hide(boolean hide) {
label.setVisibility(hide ? View.GONE : View.VISIBLE);
}
}
which maps to a single row in a RecyclerView. R.id.text is in fact the root view of the layout that gets inflated and passed in to the constructor here.
I'm using the default implementation of LinearLayoutManager.
In bindViewHolder, I call hide(true) on an instance of MyViewHolder, but instead of collapsing the row as expected, the row becomes invisible, maintaining its height and position in the RecyclerView. Has anyone else run into this issue?
How do you hide items in a RecyclerView?
There is no built in way to hide a child in RV but of course if its height becomes 0, it won't be visible :). I assume your root layout does have some min height (or exact height) that makes it still take space even though it is GONE.
Also, if you want to remove a view, remove it from the adapter, don't hide it. Is there a reason why you want to hide instead of remove ?
Put method setVisibility(boolean isVisible) in ViewHolder.
You can change itemView params(width and height) for LayoutManager:
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
...
public void setVisibility(boolean isVisible){
RecyclerView.LayoutParams param = (RecyclerView.LayoutParams)itemView.getLayoutParams();
if (isVisible){
param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
param.width = LinearLayout.LayoutParams.MATCH_PARENT;
itemView.setVisibility(View.VISIBLE);
}else{
itemView.setVisibility(View.GONE);
param.height = 0;
param.width = 0;
}
itemView.setLayoutParams(param);
}
public ViewHolder(View itemView) {
super(itemView);
...
}
}
and change visibility for ItemDecoration (Divider):
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
...
#Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
...
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i).getVisibility() == View.GONE)
continue;
/* draw dividers */
}
}
}
You CAN do it!
First, you need to detect which position of item that you want to hide. You can custom getItemViewType to do it.
Next, on onCreateViewHolder, depend on the view type. You can do something like this:
if(viewType == TYPE_HIDE) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.empty_item, parent, false);
vHolder = new ViewHolder(context, v, viewType, this);
break;
}
return vHolder;
-> empty item is a layout that have nothing, (in other word, it is default layout whenever created). or code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
Hope it help!
Okay, so the way I did it in the end was I had my whole dataset, say, myObjects and I had scenarios where I would only want to show subsets of that dataset.
Since setting visibility of rows in RecyclerView doesn't cause the heights to collapse, and setting the heights of the rows did not appear to do anything either, what I had to do was just keep a secondary dataset called myObjectsShown which was nothing more than a List<Integer> that would index into myObjects to determine which objects would be displayed.
I would then intermittently update myObjectsShown to contain the correct indices.
Therefore,
public int getItemCount() {
return myObjectsShown.size();
}
and
public void onBindViewHolder(MyViewHolder holder, int position) {
Object myObject = myObjects.get(myObjectsShown.get(position));
// bind object to viewholder here...
}
For hiding view in RecyclerView I hide/show view in OnBindViewHolder:
if (item.isShown) {
vh.FooterLayout.setVisibility(View.Visible);
} else {
vh.FooterLayout.setVisibility(View.Gone);
}
And for example - from activity I simply redraw needed item:
_postListAdapter.notifyItemChanged(position)// if you want show/hide footer - position is amountOfPosts.size() and also change bool variable - amountOfPosts[amountOfPosts.size()].isShown
For the sake of completeness, you should note that setting view visibility to GONE would not hide the margins. You need to do something like this :
if(itemView.getVisibility() != GONE) itemView.setVisibility(GONE);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) itemView.getLayoutParams();
layoutParams.setMargins(0, 0, 0, 0);
itemView.setLayoutParams(layoutParams);

Categories

Resources