Skip items in recycler view
Asked Answered
C

9

11

Hi I want to skip some items from recyclerview.

here is the screenshot

Here is the bit of code

item_Data.xml

 <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:id="@+id/mainlayout"
android:layout_height="wrap_content">
<ImageView
    android:visibility="gone"
    android:id="@id/image"
    android:layout_gravity="center"
    android:layout_width="100dp"
    android:layout_height="100dp" />
<TextView
    android:visibility="gone"
    android:textStyle="bold"
    android:id="@id/title"
    android:layout_gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"
    android:maxLength="15" />

And recycler view is

   @Override
public void onBindViewHolder(final MovieViewHolder holder, final int position) {
    String download= news.get((position)).getDownloadLinkForApkNew();
    String desc_new = news.get(position).getApkJData();
    if (download.isEmpty()==false && desc_new.isEmpty()==false) {
        holder.movieTitle.setVisibility(View.VISIBLE);
        holder.imageView.setVisibility(View.VISIBLE);
        Picasso.with(context).load(news.get((position)).getBetterFeaturedImage().getSourceUrl()).into(holder.imageView);
        holder.movieTitle.setText(news.get(position).getTitle().getRendered());
    }

I don't want the items that doesn't have download and desc_new. My logic works items are not visible but they leave there space. how can I remove the spaces between the items.

Clouded answered 5/10, 2017 at 9:48 Comment(4)
holder.itemview.setVisibility(GONE)Levant
Do you have a LinearLayout for each item of the RecyclerView ?Ppi
try something like this remove items from array list if (download.isEmpty()==true && desc_new.isEmpty()==true) { remove this item from array list }Collage
you can remove before while showing items from your data collection.Envenom
B
6

Lets go in depth as of how recycler view works

we have 2 functions onCreateView and onBindview. As the names of functions are quite self explaining onCreateView creates the view and onBindView takes the created view and binds data into it

now lets assume that entire view type is similar and you use an array of objects or cursor to populate the entire view.

so in bindView in order to fetch data you must have used either

 cursor.moveToPosition(position)

or

 mList.get(position)

as you can see that binding is happening based on the position that we get from onBindView arguments

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
     //mList.get(position) or cursor.moveToPosition
 }

so you can use this knowledge to specifically skip binding of view

say you have a function which accepts postion as parameter and returns actual position as result

private int getActualPostion(int position){
     //your logic to skip the given postion 
     //say  if(position == 4){return postion+2}
}

so you can implement something like this

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
       mList.get(getActualPosition(position));
 }

this will allow you to skip those view which are not to be shown

finally in method getCount which is used by recycler view to decide the number of views

 @Override
 public int getItemCount() {
     //foreach in array { if(already downloaded) i++} 
     // return array.size - i
 }

I hope this helps this will also give your more flexibility in a way that u may add more filters and use same dataset ... skip views more easily

Buhler answered 5/10, 2017 at 10:28 Comment(3)
I don't want to invisible specific items. I want to invisible all those items that don't fulfill my above condition. as I am getting data from the server. recycler view gets the positions of data as you explained and show it. I make some items gone by check. they are not displaying in the ui but there are spaces of the items \ @Tushar SahaClouded
it wont invisible those items ... it would skip those items as bindview wont have access to them so there wont be any spaces as well , make sure getPosition function is properly implementedBuhler
What is cursor?Bergen
N
16

There's a very simple fix for this:

If you perform view.setVisibility(View.GONE); on the view while binding it to the ViewHolder, the view would be hidden but there would still be a space right where the view was supposed to be; therefore, this approach isn't efficient.

How then do we solve this problem?

All you need to do is to set the height and/or width of the view you're trying to hide to zero. Here's a simple way to achieve this:

View Holder:

    public class MyViewHolder extends RecyclerView.ViewHolder{

        public LinearLayout.LayoutParams params;
        public LinearLayout rootView //the outermost view from your layout. Note that it doesn't necessarily have to be a LinearLayout.

        //todo: Don't forget to add your other views

        public MyViewHolder(View itemView){
            super(itemView);

            params = new LinearLayout.LayoutParams(0, 0);
            rootView = itemView.findViewById(R.id.rootView);

            //todo: Don't forget to initialize your views


        }

    }

onBindViewHolder:

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position){

    if(your_condition){
        holder.rootView.setLayoutParams(holder.params);  
        //this line hides the view completely
    }
    else{
        //todo: Do your regular stuff
    }

}

I hope this helps. Merry coding!

Nylanylghau answered 20/1, 2019 at 0:30 Comment(1)
You are the best.Thank you very much.I was suffering with this issue.Rancell
B
6

Lets go in depth as of how recycler view works

we have 2 functions onCreateView and onBindview. As the names of functions are quite self explaining onCreateView creates the view and onBindView takes the created view and binds data into it

now lets assume that entire view type is similar and you use an array of objects or cursor to populate the entire view.

so in bindView in order to fetch data you must have used either

 cursor.moveToPosition(position)

or

 mList.get(position)

as you can see that binding is happening based on the position that we get from onBindView arguments

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
     //mList.get(position) or cursor.moveToPosition
 }

so you can use this knowledge to specifically skip binding of view

say you have a function which accepts postion as parameter and returns actual position as result

private int getActualPostion(int position){
     //your logic to skip the given postion 
     //say  if(position == 4){return postion+2}
}

so you can implement something like this

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
       mList.get(getActualPosition(position));
 }

this will allow you to skip those view which are not to be shown

finally in method getCount which is used by recycler view to decide the number of views

 @Override
 public int getItemCount() {
     //foreach in array { if(already downloaded) i++} 
     // return array.size - i
 }

I hope this helps this will also give your more flexibility in a way that u may add more filters and use same dataset ... skip views more easily

Buhler answered 5/10, 2017 at 10:28 Comment(3)
I don't want to invisible specific items. I want to invisible all those items that don't fulfill my above condition. as I am getting data from the server. recycler view gets the positions of data as you explained and show it. I make some items gone by check. they are not displaying in the ui but there are spaces of the items \ @Tushar SahaClouded
it wont invisible those items ... it would skip those items as bindview wont have access to them so there wont be any spaces as well , make sure getPosition function is properly implementedBuhler
What is cursor?Bergen
E
3

You can remove the items from arraylist an then pass updated array list to adapter by this way you don't need to play with visibility of your views

Eider answered 5/10, 2017 at 10:21 Comment(0)
C
0

By making them View.INVISIBLE you are not removing the reserved spaces. Instead you could use View.GONE to make them invisible and allow the reserved space to be taken.

Since you are setting the Views visible again you have to undo it with the if-else clause e.g.

if (!download.isEmpty() && !desc_new.isEmpty()) {
    // make visible
} else {
    // make invisible with gone e.g.
    holder.movieTitle.setVisibility(View.GONE);
    holder.imageView.setVisibility(View.GONE);
}
Corbel answered 5/10, 2017 at 9:50 Comment(4)
don't use gone use invisibleEider
@Shahrozjavaid Where did you do it? Did you set it to gone in the else branch`?Ahrendt
no I set it gone in the xml. you can see the xml above. @MuratK.Clouded
@Shahrozjavaid Yes, that's why you have to set it to gone in the else branch again. Do as my answer provides please.Ahrendt
S
0
if (download.isEmpty()==true && desc_new.isEmpty()==true) {

        //Hide the items
   holder.movieTitle.setVisibility(View.GONE);
   holder.imageView.setVisibility(View.GONE);

}else {
   holder.movieTitle.setVisibility(View.VISIBLE);
   holder.imageView.setVisibility(View.VISIBLE);
   Picasso.with(context).load(news.get((position)).getBetterFeaturedImage().getSourceUrl()).into(holder.imageView);
   holder.movieTitle.setText(news.get(position).getTitle().getRendered())           
}
Spirometer answered 5/10, 2017 at 9:51 Comment(3)
but spaces are not goingClouded
you have to use view.GONE and not view.INVISIBLESpirometer
Using gone in the XMLClouded
C
0

you should use View.GONE instead of View.INVISIBLE

INVISIBLE

This view is invisible, but it still takes up space for layout purposes.

GONE

This view is invisible, and it doesn’t take any space for layout purposes.

if (download.isEmpty()==true && desc_new.isEmpty()==true) {

       holder.movieTitle.setVisibility(View.GONE);
       holder.imageView.setVisibility(View.GONE);

}else {
   holder.movieTitle.setVisibility(View.VISIBLE);
   holder.imageView.setVisibility(View.VISIBLE);
   Picasso.with(context).load(news.get((position)).getBetterFeaturedImage().getSourceUrl()).into(holder.imageView);
   holder.movieTitle.setText(news.get(position).getTitle().getRendered())           
}
Collage answered 5/10, 2017 at 9:56 Comment(2)
@Shahrozjavaid try something like this remove items from array list if (download.isEmpty()==true && desc_new.isEmpty()==true) { remove this item from array list }Collage
I want to hide all the other than I conditioned. items are not showing. there are spaces in the recycler view. I tried to solution that u are suggesting.Clouded
C
0

Simply Remove items from the list and then pass the updated list to the Adapter.

For example: I removed the items from the list in the HomePage before passing it to Users Adapter

 for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                Users user = dataSnapshot.getValue(Users.class);
                if(!FirebaseAuth.getInstance().getCurrentUser().getUid().equals(user.getUid()))
                userArrayList.add(user);
            }
Changeling answered 24/10, 2022 at 20:40 Comment(0)
R
0

What you need to do is to set the height and/or width of the view you're trying to hide to zero.Kotlin code: onBindViewHolder

override fun onBindViewHolder(holder: ChildMainHolder, position: Int) {

      if(your_condition){
          val  params = LinearLayout.LayoutParams(0, 0)
          holder.itemView.layoutParams = params
      }
      else{
          //todo: Do your regular stuff
      }

}

This is just the kotlin way of what Taslim Oseni did in the first answer all the credits for him.

Rancell answered 1/3, 2023 at 15:56 Comment(0)
C
-1

You need to set visibility to your holder, not your views.

if (download.isEmpty()==true && desc_new.isEmpty()==true) {
  holder.setVisibility(View.GONE);

}else {
   holder.setVisibility(View.VISIBLE);
   Picasso.with(context).load(news.get((position)).getBetterFeaturedImage().getSourceUrl()).into(holder.imageView);
   holder.movieTitle.setText(news.get(position).getTitle().getRendered())           
}

also delete visibility from your xml

Cozen answered 5/10, 2017 at 9:56 Comment(1)
There is no such method as setVisibility(int) in RecyclerView.ViewHolder.Mcinerney

© 2022 - 2024 — McMap. All rights reserved.