1

I am working with a Fragment that handles a RecyclerView with different adapters, but when I try to show my emptyView TextView in the RecyclerView it simply stops the RecyclerView from working properly.

I created the following filter in my adapter:

/**
     * Method that filters the data using the onQueryTextSubmit and onQueryTextChange.
     *
     * @return a Filter class that calls the method performFiltering of the FilterResults class
     * and this method applies the filter and returns a list with the resulting data filtered.
     */
@Override
public Filter getFilter() {
    return new Filter() {

        @Override
        protected FilterResults performFiltering(CharSequence querySample) {

            if (emptyView.getVisibility() == View.VISIBLE) {
                emptyView.setVisibility(View.GONE);
            }

            /*
             * Verifies the value of the sampleNameSearched and compares the data.
             */
            if (querySample == null) {
                // Updates the recyclerView with the sampleList.
                sampleListFiltered.submitList(sampleList);
                // holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
            } else {

                // Cleans the accentuation, letter case and other symbols of the querySample.
                sampleNameSearched = Normalizer.normalize(querySample.toString(), Normalizer.Form.NFD)
                        .replaceAll("[^\\p{ASCII}]", "").toLowerCase();

                // Creates the list that will save the filtered samples.
                List<Sample> filteredSampleList = new LinkedList<>();

                // Gets the data filtered in the for loop.
                for (Sample sample : sampleList) {

                    // Cleans the accentuation, letter case and other symbols.
                    String sampleName = Normalizer.normalize(sample.getName(), Normalizer.Form.NFD)
                            .replaceAll("[^\\p{ASCII}]", "").toLowerCase();

                    // Adds the sample that matches the filter in the filteredSampleList.
                    if (sampleName.contains(sampleNameSearched)) {
                        filteredSampleList.add(sample);
                    }
                }

                // Updates the RecyclerView.
                sampleListFiltered.submitList(filteredSampleList);

                // TODO: Find a solution for not showing the emptyView instantly (not entering the onBindViewHolder).
                /*
                 * if filteredSampleList is empty, shows the emptyView with the proper message.
                 */
                if (filteredSampleList.isEmpty()) {
                    // Updates the RecyclerView.
                    emptyView.setVisibility(View.VISIBLE);
                } else {
                    if (emptyView.getVisibility() == View.VISIBLE) {
                        emptyView.setVisibility(View.GONE);
                    }
                }

            }

            // Returns the filterResults.
            FilterResults filterResults = new FilterResults();
            filterResults.values = sampleListFiltered;
            return filterResults;
        }

        // Publish the results on the RecyclerView.
        @Override
        protected void publishResults(CharSequence constraint, FilterResults filterResults) {
            notifyDataSetChanged();
        }
    };
}

I cannot find out why my emptyView.setVisibility() sometimes works and others simply doesn't.

My layout is the following:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@id/search_sample_field"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="25dp"
        android:layout_marginTop="25dp"
        android:layout_marginEnd="25dp"
        app:layout_constraintTop_toBottomOf="@+id/sample_folder_selector">

        <SearchView
            android:id="@+id/sample_search_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:background="@drawable/search_box_border"
            android:clickable="true"
            android:iconifiedByDefault="false"
            android:layoutDirection="rtl"
            android:queryHint="@string/sample_search" />

    </RelativeLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/ListNavigatorRecyclerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="25dp"
        android:layout_marginTop="25dp"
        android:layout_marginEnd="25dp"
        app:layout_constraintBottom_toTopOf="@+id/ButtonPanel"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/search_sample_field"
        app:layout_constraintVertical_bias="1.0" />

    <TextView
        android:id="@+id/emptyListNavigatorView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="25dp"
        android:layout_marginEnd="25dp"
        android:layout_marginBottom="100dp"
        android:gravity="center"
        android:text=""
        android:visibility="gone"
        app:layout_constraintBottom_toTopOf="@+id/ButtonPanel"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/search_sample_field"
        app:layout_constraintVertical_bias="1.0" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/ButtonPanel"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@color/BaseColor_4"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent">

        <ImageButton
            android:id="@+id/remove_sample_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="25dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:src="@drawable/btn_delete"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"

            style="@style/IconButton" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout> 

Just to make sure that you understand the problem you can see some prints of the problem below:

What was supposed to happen:

Step 1 - Filter: Filtering

Step 2 - Writing a sample that doesn't exist: Sample that doesn't exist

Step 3 - Removing the wrong character: The wrong character removed

What is happening right now (not supposed to happen):

Step 1 - Filter (working): Filtering

Step 2 - Writing a sample that doesn't exist (not showing the emptyView): Not showing the emptyView

Step 3 - Removing the wrong character (not showing the sample nor the bold character): Not showing the sample

If I press the search button on the keyboard it works, but it was intended to work without pressing the search button...

Can someone help me with this problem?

I used a toast, and the toast works, but when it comes to using any kind of set method in the performFiltering or layout that requires a set method it seems that Android somehow losses its working flow.

I tried the following implementations:

How to show an empty view with a RecyclerView?

https://alexzh.com/how-to-setemptyview-to-recyclerview/

https://www.reddit.com/r/androiddev/comments/3bjnxi/best_way_to_handle_recyclerview_empty_state/

1 Answers1

0

How to solve this problem?

I created an EmptyRecyclerView that extends the RecyclerView behaviours and added an updateEmptyView() method that verifies how many items I have in my RecyclerView and updates the view accordingly. My solution was based on this answer by maff91. And another source that helped me solve the problem is this Google Application that creates an EmptyView message like the one I needed.

My thanks to maff91 and the Google Application that has the same behaviour.