由于Recyclerview没有setEmptyView的方法,因此必须重写有关方法:
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);
}
public 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);
}
}
public void setEmptyView(View emptyView) {
this.emptyView = emptyView;
checkIfEmpty();
}
}
注意,在setAdapter的方法中不要调用checkIfEmpty,否则不管有无数据都会先跳出emptyview!这里我把checkIfEmpty定义为公有的,需要在外部用到:
HTTPUtil_POST.sendHttpRequest(adress, postmessage, new HttpCallbackListener() {
@Override
public void onFinish(String response) {
parseJSONWithJSONObject(response);
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
@Override
public void onError(Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.checkIfEmpty();
}
});
}
});
由于网络的问题也能导致数据为空,也应该显示emptyView,但是这种情况下是不会经过onFinish的(adapter.notifyDataSetChanged()),在重写的Recyclerview里面是不会调用checkIfEmpty的,因此需要在onError里调用checkIfEmpty()。
还有一个方面,在布局文件中,由于SwipeRefreshLayout的子控件有且只能有一个,若把Recyclerview与Emptyview同时写在里面肯定是不行的。
经尝试,许多方法不行,如:
1、写两个并列的SwipeRefreshLayout,一个放RecyclerView,另一个放ScrollView并包含着EmptyView
2、一个SwipeRefreshLayout里放入FrameLayout,FrameLayout里包含RecyclerView和ScrollView...
上面两种方式在EmptyView显示上没什么问题,但有数据时显示的RecyclerView的列表不能滑动,并且丧失了点击的功能
正确的方式:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.dell.internet_pratice.EmptyRecyclerView
android:id="@+id/rv_ls"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.dell.internet_pratice.EmptyRecyclerView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<include
android:id="@+id/id_empty_view"
layout="@layout/empty_textview" />
</ScrollView>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>