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 사용할 수 있으며 빈보기뿐만 아니라로드보기 및 오류보기를 지원합니다. 기존 어댑터의 논리를 변경하지 않고도 사용할 수 있습니다.
Hieu Rocker

20
그것에 setEmptyView()대해 간단한 방법 이없는 것 같습니다 RecyclerView...
Subby

내 대답은 다음 링크를 확인하십시오. stackoverflow.com/a/58411351/5449220
Rakesh Verma

@Subby는 동의하지만 setEmptyView()단점도있었습니다. 데이터를로드 할 때에 빈보기를 표시하고 싶지 ListView는 않았지만 그랬습니다. 그래서 우리는 논리를 구현해야했습니다. 현재 stackoverflow.com/a/48049142/2914140을 사용하고 있습니다 .
CoolMind

답변:


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

1
Fragment를 사용할 때 @JJD도 마찬가지입니다. 프래그먼트 뷰를 팽창 시키면 recyclerview와 빈 뷰에 사용될 다른 레이아웃이 있습니다. 일반적으로 내 조각에서는 1) recyclerview, 2) 빈보기 및 3) 진행률 표시 줄보기가 있습니다. 나는 일반적으로 목록이 무엇이든 어댑터를 전달하지만 목록의 크기에 따라 recyclerview를 숨기고 빈을 표시하거나 그 반대로 표시합니다. recyclerview에 빈 목록이 있으면 아무것도하지 않습니다. 당신은 빈보기를 참조하십시오.
Ray Hunter

1
@stackex 검증은 Fragment 또는 onResume of Activity의 onCreateView 콜백에 있어야합니다. 이러한 방식으로, 화면이 사용자에게 표시되기 직전에 확인이 이루어지며 데이터 세트의 행 수를 늘리거나 줄이면서 작동합니다.
slellis

2
@Zapnologica 다른 방법으로 할 수 있습니다 : 이벤트 버스 (예 : greenrobots Eventbus 또는 Otto)를 사용하고 데이터 세트가 변경 될 때 어댑터를 이벤트 버스에 게시하십시오. 프래그먼트에서는 어댑터가 Eventbus.post 메소드로 전달하는 것에 해당하는 매개 변수를 갖는 메소드를 작성하고 그에 따라 레이아웃을 변경하면됩니다. 보다 간단하지만 결합 된 접근 방식은 어댑터에서 콜백 인터페이스를 작성하고 어댑터를 작성할 때 프래그먼트가 구현하도록합니다.
AgentKnopf

2
레이아웃에는 여러 개의 루트 태그가 있습니다. 전체 레이아웃 파일은 어떻게 생겼습니까?
powder366

192

내 프로젝트의 경우이 방법 RecyclerViewsetEmptyView방법으로 만들었습니다 .

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

@Sufian 아니요, 나는 그 대답을 보지 못했습니다. 동일한 방법을 찾았습니다. 그러나 그 코드는 분명히 내 것보다 더 예쁘게 보입니다 :)
maff91

2
FirebaseRecyclerAdapter와 이것을 결합하려고 시도했지만 작동하지 않았습니다. FirebaseRecyclerAdapter는 AdapterDataObserver의 onChange를 호출하지 않고 대신 onItem * -methods를 호출하기 때문입니다. `add void public void onItemRangeRemoved (int positionStart, int itemCount) {// the check} public void onItemRangeMoved (int fromPosition, int toPosition, int itemCount) {// check} // etc.를 무시합니다.`
FrankkieNL

1
관찰자가 어댑터가 null인지 확인하는 이유는 무엇입니까? 어댑터가 null 인 경우, 관찰자는 절대 호출되지 않아야합니다.
Stimsoni

16
우린 이것이 고전 Google BS라고 말할 수 있습니다. 빈보기를 추가하기 위해 이것을 구현해야합니까? cr @ psh1t SDK에 포함되어야합니다! 신을 위해!
Neon 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()oneliner이어야하지만 여기에 if숨겨진 논리 가있는 사소한 것이 있습니다. 이 논리는 어색하게도 나타나고 getItemViewType신은 다른 곳을 알고있다
Alexey Andronov

3
한 줄일 필요는 없습니다. 여러 뷰 유형이있는 경우이를 수행 할 수 있습니다.
MSpeed

숨겨진 논리는 무엇을 의미합니까? 코드는 바로 저쪽에 있습니다
radu122

1
제 생각에는이 답변이 허용되는 답변이어야합니다. 정말 mutliple보기 유형을 처리 할 수있는 방법입니다
이보 베 커스

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);

정말 신기합니다
Zhang Xiang

깨끗한 용액.
Ojonugwa Jude Ochalifu

30

Kevin의 답변이 완전하지 않기 때문에. 의 및 데이터 세트를 업데이트
하는 경우 더 정확한 답변 입니다. 아래에 다른 사용자가 추가 한 Kotlin 버전을 참조하십시오. RecyclerAdapternotifyItemInsertednotifyItemRemoved

자바:

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

가장 우아한 해결책이라고 생각합니다!
안드로이드 매니아

훌륭한 일. 레이블을 표시 할 때 RecyclerView를 숨기는 것을 잊지 마십시오
MrG

18

RVEmptyObserver

custom을 사용하는 대신을 RecyclerView확장하는 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을 리턴하십시오.

그런 다음 onCreateViewHolderviewType이 이전에 반환 한 것인지 확인하고 다른보기를 팽창시킵니다. 이 경우 해당 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또는 내가 반환해야하기 때문에 비워 0에서 getItemCount.
JJD

다음이 null 인 경우 1을 반환합니다. :)
Pedro Oliveira

다소 작동합니다. 감사합니다. -사소한 세부 사항은 빈 목록 항목을 리사이클 뷰에서 세로가운데에 놓을 수 없다는 것 입니다. 화면 상단의 텍스트 뷰 숙박 그럼에도 불구하고 내가 설정 android:layout_gravity="center"android:layout_height="match_parent"부모 재활용 뷰.
JJD

사용중인 행의 레이아웃에 따라 다릅니다. 높이가 match_parent 여야합니다. 여전히 작동하지 않으면 전역 레이아웃 리스너를 추가하고 화면과 동일한 높이와 너비를 갖도록 레이아웃 매개 변수를 설정하십시오.
Pedro Oliveira

모든 컨테이너 (활동, 조각, 선형 레이아웃, 재활용보기, 텍스트보기)가로 설정됩니다 android:layout_height="match_parent". 행이 화면 높이로 확장되지는 않습니다.
JJD

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
해당 솔루션을 사용하는 경우 메모리 할당 크기가 증가하여 열거 형을 사용하는 것만으로는 충분하지 않습니다. 상황에 따라 적절한 주석 StringDef또는 IntDef주석을 사용하여 정수 또는 문자열을 사용하십시오.
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
바시르 AL-MOMANI

2
어댑터를 특정 활동에 연결하는 것은 좋은 디자인 패턴이 아닙니다. 인터페이스를 통해이를 수행하는 것이 좋습니다
ruX

1
또한 레이아웃 오버 드로우가 발생하여 권장하지 않으며 일부 성능 문제가 발생할 수 있습니다. 자세한 내용은 youtube.com/watch?v=T52v50r-JfE 를 참조하십시오
Felipe Conde

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);
            }
        });

0

FirebaseRecyclerAdapter로 작업하는 경우를 대비 하여이 게시물은 매력으로 작동합니다 https://stackoverflow.com/a/39058636/6507009


7
이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다.
Anh Pham
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.