[android] RecyclerView의 ListView.setEmptyView와 동일

에서는 RecyclerView어댑터가 비어있을 때 표시 할 빈보기를 설정하고 싶습니다. 에 상응하는 것이 ListView.setEmptyView()있습니까?



답변

새로운 데이터 바인딩 기능을 사용 하면 레이아웃에서 직접이 작업을 수행 할 수도 있습니다.

<TextView
   android:text="No data to display."
   android:visibility="@{dataset.size() > 0 ? View.GONE : View.VISIBLE}" />

이 경우 XML의 데이터 섹션에 변수와 가져 오기를 추가하기 만하면됩니다.

<data>
<import type="android.view.View"/>
<variable
    name="dataset"
    type="java.util.List&lt;java.lang.String&gt;"
    />
</data>


답변

@dragon born과 비슷한 클래스가 있지만 더 완벽합니다. 이 요점을 기반으로 합니다 .

public class EmptyRecyclerView extends RecyclerView {
    private View emptyView;
    final private AdapterDataObserver observer = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            checkIfEmpty();
        }
    };

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

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

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

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

    @Override
    public void setAdapter(Adapter adapter) {
        final Adapter oldAdapter = getAdapter();
        if (oldAdapter != null) {
            oldAdapter.unregisterAdapterDataObserver(observer);
        }
        super.setAdapter(adapter);
        if (adapter != null) {
            adapter.registerAdapterDataObserver(observer);
        }

        checkIfEmpty();
    }

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


답변

이 링크에 제공된 솔루션 은 완벽 해 보입니다. viewType을 사용하여 emptyView를 표시 할시기를 식별합니다. 사용자 지정 RecyclerView를 만들 필요가 없습니다.

위 링크에서 코드 추가 :

package com.example.androidsampleproject;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class RecyclerViewActivity extends Activity {

RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recycler_view);
    recyclerView = (RecyclerView) findViewById(R.id.myList);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(new MyAdapter());
}


private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<String> dataList = new ArrayList<String>();

    public class EmptyViewHolder extends RecyclerView.ViewHolder {
        public EmptyViewHolder(View itemView) {
            super(itemView);
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView data;

        public ViewHolder(View v) {
            super(v);
            data = (TextView) v.findViewById(R.id.data_view);
        }
    }

    @Override
    public int getItemCount() {
        return dataList.size() > 0 ? dataList.size() : 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (dataList.size() == 0) {
            return EMPTY_VIEW;
        }
        return super.getItemViewType(position);
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder vho, final int pos) {
        if (vho instanceof ViewHolder) {
            ViewHolder vh = (ViewHolder) vho;
            String pi = dataList.get(pos);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;

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

    private static final int EMPTY_VIEW = 10;
}

}


답변

나는 단순히 다음과 같은 간단한 해결책을 선호합니다.

RecyclerView를 FrameLayout 또는 RelativeLayout 안에 TextView 또는 기타 뷰와 함께 표시하고 기본적으로 가시성이 GONE 인 빈 데이터 메시지를 표시 한 다음 어댑터 클래스에서 논리를 적용합니다.

여기에 데이터가없는 메시지가있는 TextView가 하나 있습니다.

@Override
public int getItemCount() {
    textViewNoData.setVisibility(data.size() > 0 ? View.GONE : View.VISIBLE);
    return data.size();
}


답변

시도해보십시오 RVEmptyObserver:

를 기본 빈 레이아웃으로 AdapterDataObserver간단히 설정할 수 있는의 구현입니다 . 이렇게하면 사용자 지정을 사용하고 삶을 더 힘들게 만드는 대신 기존 코드와 함께 쉽게 사용할 수 있습니다.ViewRecylerViewRecyclerView


사용 예 :

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


답변

https://gist.github.com/adelnizamutdinov/31c8f054d1af4588dc5c 기반 내 버전

public class EmptyRecyclerView extends RecyclerView {
    @Nullable
    private View emptyView;

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

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

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

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

    private final AdapterDataObserver observer = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            checkIfEmpty();
        }
    };

    @Override
    public void setAdapter(@Nullable Adapter adapter) {
        final Adapter oldAdapter = getAdapter();
        if (oldAdapter != null) {
            oldAdapter.unregisterAdapterDataObserver(observer);
        }
        super.setAdapter(adapter);
        if (adapter != null) {
            adapter.registerAdapterDataObserver(observer);
        }
        checkIfEmpty();
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (null != emptyView && (visibility == GONE || visibility == INVISIBLE)) {
            emptyView.setVisibility(GONE);
        } else {
            checkIfEmpty();
        }
    }

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


답변

Recycler.Adapter에서이 기능을 구현하고 싶습니다.

재정의 된 getItemCount 메서드에서 빈 확인 코드를 삽입합니다.

@Override
public int getItemCount() {
    if(data.size() == 0) listIsEmtpy();
    return data.size();
}