如何使用RecyclerView显示空视图?


271

我作为把一个特殊的视图布局文件中的描述ListActivity文件当没有数据显示。该视图具有id "android:id/empty"

<TextView
    android:id="@android:id/empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/no_data" />

我想知道新的RecyclerView怎么办?


2
您可以使用github.com/rockerhieu/rv-adapter-states,它不仅支持空视图,还支持加载视图和错误视图。而且您可以使用它而无需更改现有适配器的逻辑。
约克·洛克

20
令人着迷的是,似乎没有一种简单的setEmptyView()方法可以对付RecyclerView...
Subby

这是我的答案,请检查此链接stackoverflow.com/a/58411351/5449220
Rakesh Verma,

@Subby,同意,但setEmptyView()也有缺点。加载数据时,我们不想在中显示空视图ListView,但确实如此。因此,我们必须实现一些逻辑。目前,我使用stackoverflow.com/a/48049142/2914140
CoolMind

Answers:


305

在定义的相同布局上RecyclerView,添加TextView

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

<TextView
    android:id="@+id/empty_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:visibility="gone"
    android:text="@string/no_data_available" />

onCreate或相应的回调中,您需要检查提供给您的数据集是否RecyclerView为空。如果数据集为空,则RecyclerView也为空。在这种情况下,该消息将出现在屏幕上。如果不是,请更改其可见性:

private RecyclerView recyclerView;
private TextView emptyView;

// ...

recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
emptyView = (TextView) rootView.findViewById(R.id.empty_view);

// ...

if (dataset.isEmpty()) {
    recyclerView.setVisibility(View.GONE);
    emptyView.setVisibility(View.VISIBLE);
}
else {
    recyclerView.setVisibility(View.VISIBLE);
    emptyView.setVisibility(View.GONE);
}

11
这对我来说不起作用,因为片段中的回收站视图布局被夸大了,而适配器是决定显示常规项目布局还是无项目布局。
JJD 2015年

1
@JJD使用片段时,同样适用。当您为片段视图充气时,您将拥有recyclerview,然后有另一个布局将用于您的空视图。通常,在我的片段中,我将在其中拥有以下视图:1)recyclerview,2)空视图和3)progressbar视图。无论列表是什么,我通常都会通过适配器,但是基于列表的大小,我将隐藏recyclerview并显示为空,反之亦然。如果recyclerview的列表为空,则它不执行任何操作。您只会看到一个空视图。
雷·亨特

1
@stackex验证必须在Fragment的onCreateView回调或Activity的onResume中。通过这种方式,将在屏幕显示给用户之前立即进行验证,验证将同时适用于这两种情况,从而增加或减少数据集中的行数。
slellis's

2
@Zapnologica您可以采用另一种方法:使用事件总线(例如greenrobots Eventbus或Otto),然后在数据集更改时在事件总线上放置适配器贴子。在该片段中,您要做的只是创建一个方法,该方法的参数与Adapter传递给Eventbus.post方法的参数相对应,然后相应地更改布局。一种更简单但也更耦合的方法是在适配器中创建一个回调接口,并在创建适配器后由片段实现该接口。
AgentKnopf 2015年

2
在布局中,我得到了多个根标签。您的完整布局文件是什么样的?
powder366 '16

192

对于我的项目,我制作了此解决方案(RecyclerView使用setEmptyView方法):

public class RecyclerViewEmptySupport extends RecyclerView {
    private View emptyView;

    private AdapterDataObserver emptyObserver = new AdapterDataObserver() {


        @Override
        public void onChanged() {
            Adapter<?> adapter =  getAdapter();
            if(adapter != null && emptyView != null) {
                if(adapter.getItemCount() == 0) {
                    emptyView.setVisibility(View.VISIBLE);
                    RecyclerViewEmptySupport.this.setVisibility(View.GONE);
                }
                else {
                    emptyView.setVisibility(View.GONE);
                    RecyclerViewEmptySupport.this.setVisibility(View.VISIBLE);
                }
            }

        }
    };

    public RecyclerViewEmptySupport(Context context) {
        super(context);
    }

    public RecyclerViewEmptySupport(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RecyclerViewEmptySupport(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);

        if(adapter != null) {
            adapter.registerAdapterDataObserver(emptyObserver);
        }

        emptyObserver.onChanged();
    }

    public void setEmptyView(View emptyView) {
        this.emptyView = emptyView;
    }
}

您应该使用它代替RecyclerView类:

<com.maff.utils.RecyclerViewEmptySupport android:id="@+id/list1"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    />

<TextView android:id="@+id/list_empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Empty"
    />

RecyclerViewEmptySupport list = 
    (RecyclerViewEmptySupport)rootView.findViewById(R.id.list1);
list.setLayoutManager(new LinearLayoutManager(context));
list.setEmptyView(rootView.findViewById(R.id.list_empty));

2
您是从此答案中还是从此处获取此代码的?
苏菲安

@Sufian不,我没有看到这个答案,只是找到了相同的方法。但是该代码肯定比我的代码漂亮:)
maff91

2
我试图将其与FirebaseRecyclerAdapter结合使用,但没有成功。这是因为FirebaseRecyclerAdapter不会调用(AdapterDataObserver的)onChange,而是会调用onItem *方法。要使其正常工作,请添加:`重写public void onItemRangeRemoved(int positionStart,int itemCount){//检查}重写public void onItemRangeMoved(int fromPosition,int toPosition,int itemCount){//检查} //等等。
FrankkieNL 2016年

1
为什么在观察器中检查适配器是否为空?如果适配器为null,则永远不应调用观察者。
Stimsoni

16
嗯,我必须说这只是经典的Google BS。我必须实现这个只是添加一个空视图?它应该包含在他们的cr @ psh1t SDK中!为了天哪!
霓虹灯Warge

62

这是仅针对空情况使用具有不同视图类型的自定义适配器的解决方案。

public class EventAdapter extends 
    RecyclerView.Adapter<EventAdapter.ViewHolder> {

    private static final int VIEW_TYPE_EVENT = 0;
    private static final int VIEW_TYPE_DATE = 1;
    private static final int VIEW_TYPE_EMPTY = 2;

    private ArrayList items;

    public EventAdapter(ArrayList items) {
        this.items = items;
    }

    @Override
    public int getItemCount() {
        if(items.size() == 0){
            return 1;
        }else {
            return items.size();
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (items.size() == 0) {
            return VIEW_TYPE_EMPTY;
        }else{
            Object item = items.get(position);
            if (item instanceof Event) {
                return VIEW_TYPE_EVENT;
            } else {
                return VIEW_TYPE_DATE;
            }
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;
        ViewHolder vh;
        if (viewType == VIEW_TYPE_EVENT) {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event, parent, false);
            vh = new ViewHolderEvent(v);
        } else if (viewType == VIEW_TYPE_DATE) {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event_date, parent, false);
            vh = new ViewHolderDate(v);
        } else {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event_empty, parent, false);
            vh = new ViewHolder(v);
        }

        return vh;
    }

    @Override
    public void onBindViewHolder(EventAdapter.ViewHolder viewHolder, 
                                 final int position) {
        int viewType = getItemViewType(position);
        if (viewType == VIEW_TYPE_EVENT) {
            //...
        } else if (viewType == VIEW_TYPE_DATE) {
            //...
        } else if (viewType == VIEW_TYPE_EMPTY) {
            //...
        }
    }

    public static class ViewHolder extends ParentViewHolder {
        public ViewHolder(View v) {
            super(v);
        }
    }

    public static class ViewHolderDate extends ViewHolder {

        public ViewHolderDate(View v) {
            super(v);
        }
    }

    public static class ViewHolderEvent extends ViewHolder {

        public ViewHolderEvent(View v) {
            super(v);
        }
    }

}

3
@ sfk92fksdf为什么会容易出错?这是您应该在recyclerview中处理多种视图类型的方式
MSpeed

@billynomates,因为它getItemCount()应该是一个单行,但是这里我们有if一些琐碎的逻辑。这种逻辑也很尴尬地出现getItemViewType,上帝知道别的地方
Alexey Andronov

3
不必是一行。如果您有多种视图类型,这就是这样做的方法。
MSpeed

@ sfk92fksdf您所说的隐藏逻辑是什么?代码就在此处▲
radu122

1
我认为该答案应该是公认的答案。这确实是处理多种视图类型的方式
Ivo Beckers

45

我使用ViewSwitcher

<ViewSwitcher
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/switcher"
    >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <TextView android:id="@+id/text_empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/list_empty"
        android:gravity="center"
        />

</ViewSwitcher>

在代码中,您将检查光标/数据集并切换视图。

void showItems(Cursor items) {
    if (items.size() > 0) {

        mAdapter.switchCursor(items);

        if (R.id.list == mListSwitcher.getNextView().getId()) {
            mListSwitcher.showNext();
        }
    } else if (R.id.text_empty == mListSwitcher.getNextView().getId()) {
        mListSwitcher.showNext();
    }
}

另外,如果您愿意,还可以设置几行代码来设置动画

mListSwitcher.setInAnimation(slide_in_left);
mListSwitcher.setOutAnimation(slide_out_right);

这真的很新颖
张翔

清洁溶液。
Ojonugwa Jude Ochalifu

30

由于凯文的答案不完整。
这是更正确的答案,如果您使用RecyclerAdapternotifyItemInsertednotifyItemRemoved来更新数据集。请参阅下面添加的另一个用户的Kotlin版本。

Java:

mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {

    @Override
    public void onChanged() {
        super.onChanged();
        checkEmpty();
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
        super.onItemRangeInserted(positionStart, itemCount);
        checkEmpty();
    }

    @Override
    public void onItemRangeRemoved(int positionStart, int itemCount) {
        super.onItemRangeRemoved(positionStart, itemCount);
        checkEmpty();
    }

    void checkEmpty() {
        mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
    }
});

科特林

adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
    override fun onChanged() {
        super.onChanged()
        checkEmpty()
    }

    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        super.onItemRangeInserted(positionStart, itemCount)
        checkEmpty()
    }

    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        super.onItemRangeRemoved(positionStart, itemCount)
        checkEmpty()
    }

    fun checkEmpty() {
        empty_view.visibility = (if (adapter.itemCount == 0) View.VISIBLE else View.GONE)
    }
})

2
这是一个很好的解决方案。我提议对其进行编辑,其中将包含kotlin版本。
jungledev

这看起来不错,但如果多次调用swapAdapter()甚至setAdapter(),则可能无法正常工作。
Glaucus

我认为这是最优雅的解决方案!
Android发烧友

做得好。显示标签时不要忘记隐藏RecyclerView
MrG

18

RVEmptyObserver

除了使用custom之外RecyclerView,扩展an AdapterDataObserver是一个更简单的解决方案,它允许设置一个View当列表中没有项目时显示的自定义:

用法示例:

RVEmptyObserver observer = new RVEmptyObserver(recyclerView, emptyView)
rvAdapter.registerAdapterDataObserver(observer);

类:

public class RVEmptyObserver extends RecyclerView.AdapterDataObserver {
    private View emptyView;
    private RecyclerView recyclerView;

    public RVEmptyObserver(RecyclerView rv, View ev) {
        this.recyclerView = rv;
        this.emptyView    = ev;
        checkIfEmpty();
    }

    private void checkIfEmpty() {
        if (emptyView != null && recyclerView.getAdapter() != null) {
            boolean emptyViewVisible = recyclerView.getAdapter().getItemCount() == 0;
            emptyView.setVisibility(emptyViewVisible ? View.VISIBLE : View.GONE);
            recyclerView.setVisibility(emptyViewVisible ? View.GONE : View.VISIBLE);
        }
    }

    public void onChanged() { checkIfEmpty(); }
    public void onItemRangeInserted(int positionStart, int itemCount) { checkIfEmpty(); }
    public void onItemRangeRemoved(int positionStart, int itemCount) { checkIfEmpty(); }
}

我相信它会运行得更快,如果你不叫checkIfEmpty()onChanged()onItemRangeInserted()
Geekarist

我同意(这是我个人所做的事情),但这只是作为面临此问题的人们的起点。
Sheharyar

9

在适配器上getItemViewType检查适配器是否具有0个元素,如果有,则返回不同的viewType。

然后onCreateViewHolder检查您的viewType是否为您先前返回的viewType并添加不同的视图。在这种情况下,具有该TextView的布局文件

编辑

如果仍然无法正常工作,则可能需要像下面这样以编程方式设置视图的大小:

Point size = new Point();
((WindowManager)itemView.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(size);

然后,当您增加视图调用时:

inflatedView.getLayoutParams().height = size.y;
inflatedView.getLayoutParams().width = size.x;

听起来不错。但是,onCreateViewHolder当我的数据集为null空或为空时,由于必须返回0in,所以我不会进入getItemCount
JJD 2015年

如果为空,则返回1 :)
Pedro Oliveira 2015年

有点用。谢谢。-较小的细节是我无法在回收者视图中将空列表项垂直居中。尽管如此,文本视图仍位于屏幕顶部,android:layout_gravity="center"android:layout_height="match_parent"对于父回收者视图,该文本视图仍位于屏幕顶部。
JJD 2015年

这取决于您使用的行的布局。它的高度应为match_parent。如果仍然无法使用,请添加全局布局侦听器,并将其布局参数设置为与屏幕相同的高度和宽度。
Pedro Oliveira'2

所有容器(活动,片段,线性布局,回收者视图,文本视图)均设置为android:layout_height="match_parent"。虽然该行不会扩展到屏幕高度。
JJD 2015年

8

这是我的班级,用于显示空视图,重试视图(加载api失败时)和加载进度 RecyclerView

public class RecyclerViewEmptyRetryGroup extends RelativeLayout {
    private RecyclerView mRecyclerView;
    private LinearLayout mEmptyView;
    private LinearLayout mRetryView;
    private ProgressBar mProgressBar;
    private OnRetryClick mOnRetryClick;

    public RecyclerViewEmptyRetryGroup(Context context) {
        this(context, null);
    }

    public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onViewAdded(View child) {
        super.onViewAdded(child);
        if (child.getId() == R.id.recyclerView) {
            mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            return;
        }
        if (child.getId() == R.id.layout_empty) {
            mEmptyView = (LinearLayout) findViewById(R.id.layout_empty);
            return;
        }
        if (child.getId() == R.id.layout_retry) {
            mRetryView = (LinearLayout) findViewById(R.id.layout_retry);
            mRetryView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mRetryView.setVisibility(View.GONE);
                    mOnRetryClick.onRetry();
                }
            });
            return;
        }
        if (child.getId() == R.id.progress_bar) {
            mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
        }
    }

    public void loading() {
        mRetryView.setVisibility(View.GONE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.VISIBLE);
    }

    public void empty() {
        mEmptyView.setVisibility(View.VISIBLE);
        mRetryView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public void retry() {
        mRetryView.setVisibility(View.VISIBLE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public void success() {
        mRetryView.setVisibility(View.GONE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public void setOnRetryClick(OnRetryClick onRetryClick) {
        mOnRetryClick = onRetryClick;
    }

    public interface OnRetryClick {
        void onRetry();
    }
}

activity_xml

<...RecyclerViewEmptyRetryGroup
        android:id="@+id/recyclerViewEmptyRetryGroup">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"/>

        <LinearLayout
            android:id="@+id/layout_empty">
            ...
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_retry">
            ...
        </LinearLayout>

        <ProgressBar
            android:id="@+id/progress_bar"/>

</...RecyclerViewEmptyRetryGroup>

在此处输入图片说明

来源在这里https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry


7

在自定义RecyclerView中使用AdapterDataObserver

科特林:

RecyclerViewEnum.kt

enum class RecyclerViewEnum {
    LOADING,
    NORMAL,
    EMPTY_STATE
}

RecyclerViewEmptyLoadingSupport.kt

class RecyclerViewEmptyLoadingSupport : RecyclerView {

    var stateView: RecyclerViewEnum? = RecyclerViewEnum.LOADING
        set(value) {
            field = value
            setState()
        }
    var emptyStateView: View? = null
    var loadingStateView: View? = null


    constructor(context: Context) : super(context) {}

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}


    private val dataObserver = object : AdapterDataObserver() {
        override fun onChanged() {
            onChangeState()
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            super.onItemRangeRemoved(positionStart, itemCount)
            onChangeState()
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            super.onItemRangeInserted(positionStart, itemCount)
            onChangeState()
        }
    }


    override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
        super.setAdapter(adapter)
        adapter?.registerAdapterDataObserver(dataObserver)
        dataObserver.onChanged()
    }


    fun onChangeState() {
        if (adapter?.itemCount == 0) {
            emptyStateView?.visibility = View.VISIBLE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
        } else {
            emptyStateView?.visibility = View.GONE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
        }
    }

    private fun setState() {

        when (this.stateView) {
            RecyclerViewEnum.LOADING -> {
                loadingStateView?.visibility = View.VISIBLE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.GONE
            }

            RecyclerViewEnum.NORMAL -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
                emptyStateView?.visibility = View.GONE
            }
            RecyclerViewEnum.EMPTY_STATE -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.VISIBLE
            }
        }
    }
}

layout.xml

<?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="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/emptyView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/emptyLabelTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="empty" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/loadingView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="45dp"
            android:layout_height="45dp"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:theme="@style/progressBarBlue" />
    </LinearLayout>

    <com.peeyade.components.recyclerView.RecyclerViewEmptyLoadingSupport
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

在活动中使用这种方式:

recyclerView?.apply {
        layoutManager = GridLayoutManager(context, 2)
        emptyStateView = emptyView
        loadingStateView = loadingView
        adapter = adapterGrid
    }

    // you can set LoadingView or emptyView manual
    recyclerView.stateView = RecyclerViewEnum.EMPTY_STATE
    recyclerView.stateView = RecyclerViewEnum.LOADING

1
如果使用该解决方案,请注意,由于增加了内存分配大小,因此使用枚举是不够的。根据您的上下文,使用带适当值StringDefIntDef注释的Integer或String
Andrii Artamonov,

2

我添加RecyclerView和替代ImageViewRelativeLayout

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/no_active_jobs"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_active_jobs" />

    <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

然后在Adapter

@Override
public int getItemCount() {
    if (mOrders.size() == 0) {
        mRecyclerView.setVisibility(View.INVISIBLE);
    } else {
        mRecyclerView.setVisibility(View.VISIBLE);
    }
    return mOrders.size();
}

7
如何到达mRecyclerView内部Adapter
Basheer AL-MOMANI 2016年

2
将Adapter绑定到特定Activity并不是一个好的设计模式。最好通过接口来做到这一点
ruX 2016年

1
另外,这还会导致布局透支,因此不建议这样做,并且可能会导致一些性能问题。见youtube.com/watch?v=T52v50r-JfE更多细节
菲利普·孔德

1

另一种方法是使用addOnChildAttachStateChangeListener来处理中出现/消失的子视图RecyclerView

recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onChildViewDetachedFromWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.VISIBLE);
            }
        });

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.