6

I'm trying to implement an EmptyView on my RecyclerView Adapter but I'm not getting any result.

I've followed this tutorial and this tip, but noone worked for me.

I've implemented:

if (viewType == EMPTY_VIEW) {
    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.empty_view, parent, false);
    EmptyViewHolder evh = new EmptyViewHolder(v);
    return evh;
}

v = LayoutInflater.from(parent.getContext()).inflate(R.layout.data_row, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;

But it doesn't let me compile because they are differents ViewHolder, because I've created two ViewHolder classes but they extends Recycler.ViewHolder so I don't get it...

I'm trying to do this because I've got a SearchView and I want when the list is empty it shows an EmptyView, I've got it doing it programmatically but I prefer to add like a layout because I don't know that much how to put TextViews and Buttons programmatically.

Also if I put

return dataList.size() > 0 ? dataList.size() : 1;

It gives to me error because index is 0.

I've debugged the viewType and always is 1, then it won't join the if condition...

Deep on Android I found this :

/**
 * Return the view type of the item at <code>position</code> for the purposes
 * of view recycling.
 *
 * <p>The default implementation of this method returns 0, making the assumption of
 * a single view type for the adapter. Unlike ListView adapters, types need not
 * be contiguous. Consider using id resources to uniquely identify item view types.
 *
 * @param position position to query
 * @return integer value identifying the type of the view needed to represent the item at
 *                 <code>position</code>. Type codes need not be contiguous.
 */
 public int getItemViewType(int position) {
    return 0;
 }

But the thing is that no changes the value.

EDIT

I almost done it, I did this :

 @Override
public int getItemViewType(int position) {

    return list.size() > 0 ? list.size() : 1;
}

But sometimes it returns 0 when the size() is 0... I don't get it, I'm using this SearchView, and sometimes when I type a letter that doesn't matches with any item of the list it doesn't show and sometimes it does...

Also other thing that happens is that when the layout popups it shows on the left of the screen when I put that is on center, but I think it's problem with RecyclerView because the layout puts inside of it.

RecyclerView layout :

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:id="@+id/rtpew"
    android:layout_centerInParent="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    >
         <LinearLayout android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/linearpew">
            <android.support.v7.widget.RecyclerView
             android:id="@+id/rv"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
            />
         </LinearLayout>
 </RelativeLayout>

And this is my emptylayout :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true">
<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ImageViewSearchFail"
    android:src="@drawable/sadface"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true" />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:layout_gravity="center"
    android:textSize="@dimen/15dp"
    android:layout_marginTop="4dp"
    android:text="foo"
    android:layout_below="@+id/ImageViewSearchFail"
    android:layout_centerHorizontal="true" />
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ButtonAddEntity"
    android:text="foo"
    android:background="?android:selectableItemBackground"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />
</RelativeLayout>

The other way that I thought is to implement it programmatically as follow :

   @Override
public boolean onQueryTextChange(String query) {
    final ArrayList<List> filteredModelList = filter(mModel, query);
        mAdapter.animateTo(filteredModelList);
        rv.scrollToPosition(0);
    if(query.isEmpty()){
            //Here
    }
  return true;
}

And :

private ArrayList<List> filter(ArrayList<List> models, String query) {
    query = query.toLowerCase();
    final ArrayList<List> filteredModelList = new ArrayList<List>();
    for (List model : models) {
        final String text = model.getRedName().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    if (filteredModelList.size()<0) {
           //HERE
    }
    else{
           //Delete the views added
    }
    return filteredModelList;
}

PROBLEMS

-I only add the view using the @Jimeux answer but I'd like to do this on the Adapter, I got it, but not always shows the view even if the list is empty.

-At the time to put the emptyview.xml it puts inside of the RecyclerView then since I've put all of this xml at the center it shows on the right. I've tried to add the xml programmatically but it's like a chaos....

Community
  • 1
  • 1
Skizo-ozᴉʞS
  • 16,233
  • 16
  • 66
  • 129

5 Answers5

3

Follow the below steps one by one

1). Since you have two types of views for your RecyclerView item, your adapter declaration should look like this a generic one

public class YourAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 

and your ViewHolders for both listview item and empty view should extend RecyclerView.ViewHolder like this

 static class ListItemViewHolder extends RecyclerView.ViewHolder {

        public ListItemViewHolder(View itemView) {
            super(itemView);
            // initialize your views here for list items
        }
    }

static class EmptyViewViewHolder extends RecyclerView.ViewHolder {

        public EmptyViewViewHolder(View itemView) {
            super(itemView);
            // initialize your views here for empty list
        }
    }

2). You have to Override getItemCount() and getItemViewType()

@Override
    public int getItemCount() {
        return yourList.size() > 0 ? yourList.size() : 1;// if size of your list is greater than 0, you will return your size of list otherwise 1 for the empty view.
    }

    @Override
    public int getItemViewType(int position) {
        if (yourList.size() == 0) {
            return VIEW_TYPE_EMPTY;
        }
        return position;
    }

3). Your onCreateViewHolder() will look alike this now

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TYPE_EMPTY) {
        return new EmptyViewViewHolder(mLayoutInflater
                .inflate(R.layout.empty_view_layout, parent, false));
    } else {
        return new ListItemViewHolder(mLayoutInflater
                .inflate(R.layout.row_list_item, parent, false));
    }
}

4). Same check you have to apply in your onBindViewHolder() as well

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == VIEW_TYPE_EMPTY) {
            EmptyViewViewHolder emptyViewViewHolder = (EmptyViewViewHolder) holder;
            // set values for your empty views
        } else {
            ListItemViewHolder listItemViewHolder = (ListItemViewHolder) holder;
            // set values for your list items
        }
    }

5). At last Override your SearcView.setOnQueryTextListener()

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                currentSearchKeyword = newText.trim();
                if(currentSearchKeyword.iseEmpty()){
                    yourList.clear();
                    yourAdapter.notifyDataSetChanged();
                }else{
                   // there will two cases again 1). If your currentSearchKeyword matchces with list results, add that items to your list and notify your adapter. 2) If the currentSearchKeyword doesn't matched with list results, clear your list and notify your adapter;
                }
                return false;
            }
        });

Hope it will help you, let me know if any issues.

Mukesh Rana
  • 3,873
  • 3
  • 24
  • 38
  • Thanks for your answer ill tes it as far as Im on home and I'll let you know – Skizo-ozᴉʞS Jan 24 '16 at 11:13
  • I didnt test it BUT do you know why my old code is inflating the view inside of the recycler view? – Skizo-ozᴉʞS Jan 24 '16 at 11:16
  • I didn't get what you are trying to say by this line inflating the view inside of the RecyclerView? you meant to say the empty view? why it is not showing ? – Mukesh Rana Jan 24 '16 at 11:19
  • No no, my old code had something simliar of all of your questions, BUT the problem is that when I type kajd(no matches) inside of the recycler view(i know its inside because it did the animation to scroll and the new layout was inside of it) ill test with your answer and ill see if it still ocurring :) – Skizo-ozᴉʞS Jan 24 '16 at 11:22
  • you please go through each and every step I mentioned, your problem is not a big one, all you need to take care about is handling, how you are handling result cases for your searching results. – Mukesh Rana Jan 24 '16 at 11:29
  • Did it what's : currentSearchKeyword? – Skizo-ozᴉʞS Jan 24 '16 at 13:07
  • I know what is it, the problem is that the layout is always shown.... :S I mean the emptylayout – Skizo-ozᴉʞS Jan 24 '16 at 13:40
  • Hey, sorry for the delayed response, currentSearchKeyword is just a String variable ,you can declare it at the top. And you still have the same problem after trying every step I mentioned? – Mukesh Rana Jan 25 '16 at 05:09
  • Yes... I'm having the same problem – Skizo-ozᴉʞS Jan 25 '16 at 06:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101561/discussion-between-mukesh-rana-and-skizo). – Mukesh Rana Jan 25 '16 at 06:55
  • Hey bro can you check out this [question](https://stackoverflow.com/questions/50655579/custom-imageview-class-onclick-change-imageresource) please? – Skizo-ozᴉʞS Jun 02 '18 at 11:11
  • Best answer from far ! No need to add "empty" data or some strange stuff – Zhar Dec 07 '19 at 09:17
3

Since you need to handle two different kind of views, it would be easier to use an intermediate list of business object for more easily binding them with views. Idea is to have a kind of placeholder in your list for representing empty state. Defining an intermediate layer is extremely useful in this sense for allowing you to consider eventual changes to be applied to your list in future (e.g. adding you element types). Moreover in this way you can more clearly separate your business model from ui representation (for example you can implement methods returning ui settings based on internal status of model objects).

You can proceed as follows:

  1. Define a dedicated abstract type for List items (e.g. ListItem) to wrap your business objects. Its implementation could be something like this:

    public abstract class ListItem {
    
        public static final int TYPE_EMPTY = 0;
        public static final int TYPE_MY_OBJ = 1;
    
        abstract public int getType();
    
    }  
    
  2. Define a class for each of your List element type:

    public class EmptyItem extends ListItem {
    
        @Override
        public int getType() {
            return TYPE_EMPTY;
        }
    
    }
    
    public class MyObjItem extends ListItem {
    
        private MyObj obj;
    
        public ContactItem(MyObj obj) {
            this.obj = obj;
        }
    
        public MyObj getMyObj() {
            return obj;
        }
    
        // here you can also add methods for simplify
        // objects rendering (e.g. get background color
        // based on your object internal status)
    
        @Override
        public int getType() {
            return TYPE_MY_OBJ;
        }
    
    }
    
  3. Create your list.

    List<ListItem> mItems = new ArrayList<>();
    if (dataList != null && dataList.size() > 0) {
        for (MyObj obj : dataList) {
            mItems.add(new MyObjItem(obj));
        }
    } else {
        mItems.add(new EmptyItem());
    }
    

    This is the most important part of code. You have many options for creating this list. You can do it inside your RecyclerView Adapter or outside, but it's extremely important to properly handle eventual modifications to it. This is essential for exploiting Adapter notify methods. For example, if you create list within the Adapter, it should probably provide also methods for adding or removing your model items. For example:

    public void addObj(MyObj obj) {
        if (mItems.size() == 1 && mItems.get(0).getType() == ListItem.EMPTY_TYPE) {
            mItems.clear();
        }
        mItems.add(new MyObjItem(obj));
        notifyDataSetChanged();
    } 
    
  4. Define an adapter for your RecyclerView, working on List defined at point 3. Here what is important is to override getItemViewType method as follows:

    @Override
    public int getItemViewType(int position) {
        return mItems.get(position).getType();
    }
    

Moreover, type of ViewHolder should be RecyclerView.ViewHolder (unless you decide to create an intermediate class even in this case).

  1. Then you need to have two layouts and ViewHolder for empty and business obj items. Adapter methods should take care of this accordingly:

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ListItem.TYPE_EMPTY) {
            View itemView = mLayoutInflater.inflate(R.layout.empty_layout, parent, false);
            return new EmptyViewHolder(itemView);
        } else {
            View itemView = mLayoutInflater.inflate(R.layout.myobj_layout, parent, false);
            return new MyObjViewHolder(itemView);
        }
    }
    
    
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
        int type = getItemViewType(position);
        if (type == ListItem.TYPE_EMPTY) {
            EmptyItem header = (EmptyItem) mItems.get(position);
            EmptyViewHolder holder = (EmptyViewHolder) viewHolder;
            // your logic here... probably nothing to do since it's empty
        } else {            
            MyObjItem event = (MyObjItem) mItems.get(position);
            MyObjViewHolder holder = (MyObjViewHolder) viewHolder;
            // your logic here
        }
    }
    

Of course, as I wrote at the beginning you don't need to strictly define intermediate types for ui representation (EmptyItem and MyObjItem). You can even just use MyObj type and create a specific configuration for it that represent an empty placeholder. This approach is probably not the best in case in future you need to make your logic more complex by including for example new list item types.

thetonrifles
  • 4,027
  • 2
  • 19
  • 20
  • Thanks for the reply, by the way why I need to put the EmptyObject as a List? – Skizo-ozᴉʞS Jan 25 '16 at 12:27
  • @Skizo Well, idea is to create a binding between `ListItem`s and `View`s in your `RecyclerView`. Since you want to include a view in your `RecyclerView` in case your business object list is empty, you can represent this situation with a dedicated `ListItem`. With this approach, in future you will be also able to eventually add headers for groups of items or loader item on bottom of the list. Hope I was clear with my explanation. In case of course ask me additional questions. – thetonrifles Jan 25 '16 at 12:39
  • And why the way I was trying to use doesn't work... I followed some tutos and they does the same :S – Skizo-ozᴉʞS Jan 25 '16 at 12:49
  • @Skizo You mean defining a type for `ListItem`s doesn't allow you to see the default view in your empty `RecyclerView`? I can develop a sample project with these concepts applied (maybe it's easier for me than writing comments :)). Just I think I need some hours because now I'm not at home. – thetonrifles Jan 25 '16 at 12:55
  • No, the way I'm doing this (My quesiton I've put some code) and why it doens't work if it should.... – Skizo-ozᴉʞS Jan 25 '16 at 13:11
  • @Skizo ok, as soon as possible I better check your approach then – thetonrifles Jan 25 '16 at 13:13
  • Yap thanks... I think it's a foolly thing that I missed or something – Skizo-ozᴉʞS Jan 25 '16 at 13:17
  • No problem... I like to deal with recyclerview / listview stuffs – thetonrifles Jan 25 '16 at 13:19
  • Okay, if you need more code just let me know and I'll send it to you – Skizo-ozᴉʞS Jan 25 '16 at 13:29
  • @Skizo [Here](https://github.com/thetonrifles/android-recycler-view) I've put code of a sample application implementing two approaches for `RecyclerView` with `SearchView` and empty view. Main Activity will allow you to switch between the two `RecyclerView`. First solution is the one I also reported in my answer, second one is the one you implemented... at least as far as I understood. Now they seems to work both. Maybe you can check them or provide me your code to check in case your implementation doesn't match at all with mine. – thetonrifles Jan 25 '16 at 22:08
  • Thanks, I'll take a look .... by the way is this any issue if instead of declare the list as List mContacts; I declare as ArrayList mContacts;? – Skizo-ozᴉʞS Jan 26 '16 at 00:07
  • @Skizo Declaring mContacts as List just means that you are expecting to use it according to the interface provided in List, so exploiting just its methods. ArrayList implements List so there's no issue in turning List mContacts declaration into ArrayList mContacts. Problem could be to do the opposite if in your code you use methods defined in ArrayList that are not declared in List interface. – thetonrifles Jan 26 '16 at 00:29
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101634/discussion-between-skizo-and-thetonrifles). – Skizo-ozᴉʞS Jan 26 '16 at 00:30
  • can you come in chat please? – Skizo-ozᴉʞS Jan 26 '16 at 00:39
  • @Skizo I'm available in chat – thetonrifles Jan 26 '16 at 11:51
  • Hey bro can you check out this [question](https://stackoverflow.com/questions/50655579/custom-imageview-class-onclick-change-imageresource) please? – Skizo-ozᴉʞS Jun 02 '18 at 11:11
  • @Skizo-ozᴉʞS sorry, I didn't have time to check yet, but I see right now that you solved your problem, right? – thetonrifles Jun 07 '18 at 08:33
2

The compilation error probably results because of you extending RecyclerView.Adapter with your main ViewHolder as the generic argument.

You should make it like

YourAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>

And then cast your ViewHolders appropriately (you can reuse getViewType(position) here). Be sure to switch the ViewHolder type in your methods as well.

David Medenjak
  • 31,688
  • 14
  • 100
  • 129
  • The thing is that I've this : `public class Adaptergg extends RecyclerView.Adapter {` – Skizo-ozᴉʞS Jan 20 '16 at 00:17
  • @Skizo Exactly. Unless `Adapter.ViewHolder` is the superclass of `EmptyViewHolder` you should change that – David Medenjak Jan 20 '16 at 00:18
  • But I don't get it, the two Viewholder classes are extending RecyclerView.viewHolder and if I put one it works, but when I try to put the second one it crashes – Skizo-ozᴉʞS Jan 20 '16 at 00:20
  • @Skizo `extends RecyclerView.Adapter` – David Medenjak Jan 20 '16 at 00:23
  • So I can't do it with ? I changed to Recycler.ViewHolder, and in onBindViewHolder it doesn't moddify the holder it means I can't do holder.tvHello.setText("SD"); – Skizo-ozᴉʞS Jan 20 '16 at 00:24
  • @Skizo I don't know what you're asking. You are using generics but provide just one specific Type without accounting for the other. Please have a look at java, generics and inheritances, the first sample you linked in your question also uses `RecyclerView.ViewHolder` as the generic type, so does the second, if you just adapt your code and cast appropriately it will work – David Medenjak Jan 20 '16 at 00:29
  • I've adapted it and doesn't show the new layout :S, I think that's because the viewType never changes .... – Skizo-ozᴉʞS Jan 20 '16 at 00:32
2

If I were you, I wouldn't put the empty view in the adapter at all. Put it under your linearpew layout that's holding the RecyclerView and hide/show it as your data changes. You can easily add a loading view, error view, etc. with this setup too.

Here's a bit of simplified code from one of my apps to give you some ideas. @Bind comes from Butter Knife if you're not familiar with it. You may also want to check out Jake Wharton's u2020 project for more RecyclerView ideas.

//fragment_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/content">
    </FrameLayout>

    <include layout="@layout/status_views" />

</RelativeLayout>

//status_views.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <LinearLayout style="@style/ListStatusView"
        android:id="@+id/empty_view"/>

    <LinearLayout style="@style/ListStatusView"
        android:id="@+id/error_view"/>

    <LinearLayout style="@style/ListStatusView"
        android:id="@+id/loading_view"
        android:padding="30dp"/>

</LinearLayout>

//MyFragment.java
@Bind(R.id.content)      protected ViewGroup contentView;
@Bind(R.id.loading_view) protected ViewGroup loadingView;
@Bind(R.id.empty_view)   protected ViewGroup emptyView;
@Bind(R.id.error_view)   protected ViewGroup errorView;

@Bind({R.id.loading_view, R.id.error_view, R.id.empty_view, R.id.content})
protected List<ViewGroup> stateViews;

protected void activateView(View view) {
    for (ViewGroup vg : stateViews)
        vg.setVisibility(View.GONE);

    view.setVisibility(VISIBLE);
}

@Override
public void onActivityCreated(@Nullable Bundle state) {
    super.onActivityCreated(state);
    if (state == null) {
        activateView(loadingView);
        loadData();
    } else if (data.isEmpty())
        activateView(emptyView);
    else
        activateView(contentView);
}

Edit: Here's a simplified version without Butter Knife.

private ViewGroup contentView;
private ViewGroup emptyView;

@Override
protected void onCreate(@Nullable Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.activity_main);
    contentView = (ViewGroup) findViewById(R.id.content_view);
    emptyView = (ViewGroup) findViewById(R.id.empty_view);
}

@Override
public boolean onQueryTextChange(String query) {
    final ArrayList<List> filteredModelList = filter(mModel, query);
    mAdapter.animateTo(filteredModelList);
    rv.scrollToPosition(0);

    if(query.isEmpty()){
        contentView.setVisibility(View.GONE);
        emptyView.setVisibility(View.VISIBLE);
    } else {
        contentView.setVisibility(View.VISIBLE);
        emptyView.setVisibility(View.GONE);
    }
    return true;
}

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rtpew"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true">

    <LinearLayout
        android:id="@+id/content_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <RelativeLayout android:id="@+id/empty_view">
        <ImageView android:src="@drawable/sadface"/>
        <TextView android:text="foo"/>
        <Button android:id="@+id/ButtonAddEntity"/>
    </RelativeLayout>
</RelativeLayout>
Jimeux
  • 2,720
  • 1
  • 16
  • 14
  • Could you post an example for an Activity since I'm on an Activity. And what shall I remove from my code? I have to re-do the adapter? – Skizo-ozᴉʞS Jan 20 '16 at 02:17
  • Can you show to me your app that does thi function? – Skizo-ozᴉʞS Jan 20 '16 at 02:20
  • All you need is the empty view layout in your Activity layout XML and a reference to it in the Activity code. Then you can hide/show it whenever you want. You can delete the empty view code from the Adapter and just leave it as it is. – Jimeux Jan 20 '16 at 02:26
  • I have the empty layout as xml but read my problem it goes to the left because of recyclerview... – Skizo-ozᴉʞS Jan 20 '16 at 02:28
  • Yes, it could be a solution, but since I really don't want to make that much comparations the adapter idea would be perfect.... I'll wait until someone answer this post doing it with the adapter, otherwise your answer will be the correct one. – Skizo-ozᴉʞS Jan 20 '16 at 07:22
1

Here is what you can try:

1. Replace

EmptyViewHolder evh = new EmptyViewHolder(v);

with

RecyclerView.ViewHolder evh = new EmptyViewHolder(v);

This is probably why the compilation fails.

2. Replace

@Override
public int getItemViewType(int position) {
    return list.size() > 0 ? list.size() : 1;
}

with

@Override
public int getItemViewType(int position) {
    return list.get(position) != null ? 1 : 0;
}

For this to work, you must insert a null object whenever you want to show an EmptyView:

int progressPosition = list.size();
list.add(null);
adapter.notifyItemInserted(progressPosition);

and remove the null object when you want to hide the EmptyView:

int progressPosition = existingList.size() - 1;
existingList.remove(progressPosition);
adapter.notifyItemRemoved(progressPosition);

Also, you must modify your onCreateViewHolder() method as follows:

 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 1) {
            // inflate your default ViewHolder here ...
        } else {
            // inflate the EmptyViewHolder here
        }
    }

I believe we have discussed this before ... see this question for a detailed discussion on this.

3. Instead of using a SearchView, consider using an AutoCompleteTextView with a Filter. This may be easier to integrate with your RecyclerView's Adapter. See this answer for an example of this.

I will update this answer as I understand your question better ... do try this and update me.

Community
  • 1
  • 1
Y.S
  • 28,153
  • 12
  • 86
  • 113
  • Hey master, thanks for the replay... Ill test the answer as soon as I'm with my notebook.. Btw, what you don't understand? And where do I put the null object? I mean the progressposition – Skizo-ozᴉʞS Jan 22 '16 at 06:13
  • I need to study your answer in more detail ... :) when you want to show the EmptyView, you need to insert the null object in the dataset, and remove it when you want to hide the EmptyView. – Y.S Jan 22 '16 at 06:22
  • But you mean on searchview? – Skizo-ozᴉʞS Jan 22 '16 at 06:24
  • In what part tho? Onviewholdercreated? – Skizo-ozᴉʞS Jan 22 '16 at 06:36
  • That depends on what you are doing in your Activity / Fragment ... Where you want to show the EmptyView ... – Y.S Jan 22 '16 at 06:38
  • Oh that was I meant that where I'm doing now the comparation for a unmatched query I add this, right? – Skizo-ozᴉʞS Jan 22 '16 at 06:40
  • In your code, you need to insert the null object whenever you want to show the EmptyView, and remove the null object whenever you want to hide the EmptyView ... Add and Remove from the RecyclerView's dataset ... :) – Y.S Jan 22 '16 at 06:45
  • The problem is what I said on the question it doesn't show the emptyview filled on the screen It means that it puts inside of the RecyclerView and to the left... :S – Skizo-ozᴉʞS Jan 22 '16 at 07:24
  • I think it's because we are working on the adapter and the adapter is for the RV I wanted to remove that RV and then add the emptyview – Skizo-ozᴉʞS Jan 22 '16 at 12:24
  • Did you try the suggestions? – Y.S Jan 24 '16 at 08:24
  • I tried it but I'm not clear when I put the null object, I tried to put it on my onTextChange and when query doesnt match with any name of list just add the null, right? – Skizo-ozᴉʞS Jan 24 '16 at 08:54
  • When I put your method getItemViewType I get : `java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0` and on Remove method `java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1` – Skizo-ozᴉʞS Jan 24 '16 at 13:32
  • Actually, it is not clear from your comments what you want exactly ... Let me have a better look at your question again ... What I have suggested should work ... – Y.S Jan 24 '16 at 14:51
  • I think I've explained my question pretty well... the thing that I'm trying is on my Activity I've got a gridview of recyclerviews that those have an adapter... and on the same activity I've created the same SearcView than the answer (question link) and I'm trying to when the query doesn't match with any name of the list it shows an empty view(customized) and if it matches it shows the result(it allready does this function) hope you understand me now – Skizo-ozᴉʞS Jan 24 '16 at 14:57
  • Hey bro can you check out this [question](https://stackoverflow.com/questions/50655579/custom-imageview-class-onclick-change-imageresource) please? – Skizo-ozᴉʞS Jun 02 '18 at 11:11