如何在 RecyclerView 中创建一个空视图?

How to create an empty view in a RecyclerView?

我正在使用处理具有不同适配器的 RecyclerView 的 Fragment,但是当我尝试在 RecyclerView 中显示我的 emptyView TextView 时,它只会阻止 RecyclerView 正常工作。

我在适配器中创建了以下过滤器:

/**
     * 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();
        }
    };
}

我无法找出为什么我的 emptyView.setVisibility() 有时有效而其他的根本无效。

我的布局如下:

<?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> 

为了确保您理解问题,您可以在下面查看问题的一些打印件:

应该发生什么:

第 1 步 - 过滤器: Filtering

第 2 步 - 编写一个不存在的示例: Sample that doesn't exist

第 3 步 - 删除错误字符: The wrong character removed

现在正在发生的事情(不应该发生的):

第 1 步 - 过滤器(工作): Filtering

第 2 步 - 编写一个不存在的示例(不显示 emptyView): Not showing the emptyView

第 3 步 - 删除错误字符(不显示样本或粗体字符): Not showing the sample

如果我按下键盘上的搜索按钮,它就可以工作,但它本应在不按下搜索按钮的情况下工作...

有人可以帮我解决这个问题吗?

我使用了 toast,并且 toast 有效,但是当涉及到在 performFiltering 或需要 set 方法的布局中使用任何类型的 set 方法时,Android 似乎以某种方式失去了它的工作流程。

我尝试了以下实现:

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

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

如何解决这个问题?

我创建了一个扩展 RecyclerView 行为的 EmptyRecyclerView 并添加了一个 updateEmptyView() 方法来验证我的 RecyclerView 中有多少项目并相应地更新视图。我的解决方案基于此 . And another source that helped me solve the problem is this Google Application,它创建了一条我需要的 EmptyView 消息。

感谢 maff91 和具有相同行为的 Google 应用程序。