在App界面里,如果列表中没有元素,界面就会一片空白(列表区域往往是占满大部分屏幕的)。为了避免这种大面积空白的情况,可以在空白的时候显示一行小字,起到提示用户进行下一步操作的作用,也有补位的效果。
Activity中的情况
这种情况比较容易实现,思路是新建一个与RecyclerView同级的TextView元素,将其Visibility属性设为gone(invisible会使得对应位置空白,仍然占用布局空间)。在Activity的回调函数中(参考Activity的生命周期),保证每一次列表更新后,检查列表是否为空,若为空则将RecyclerView的visibility设为gone,TextView的visibility设为visible,此时文字便显现出来。不为空时再改回原样。
参考代码如下:
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);
}
参考自下列链接:How to show an empty view with a RecyclerView?
Fragment中的情况
然而,现在很多的RecyclerView并不直接是Activity的根元素,尤其是作为Fragment实现时,上述方法不能直接用。参考上面链接中回答者的进一步说明,我实现了相关情况,下面是效果图:
思路其实与上面Activity的情况相同,不同之处在于,检查列表是否为空的操作放在Fragment的回调函数中实现。
代码如下:
public class DeadlineFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
private SwipeRefreshLayout swipeRefreshLayout;
private View view;
public DeadlineList deadlineList;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_deadline, container, false);
RecyclerView recyclerView = view.findViewById(R.id.deadline_recyclerview);
swipeRefreshLayout = view.findViewById(R.id.deadline_swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setProgressViewOffset(true, 0, 50);
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
onRefresh();
}
});
deadlineList = new DeadlineList();
deadlineList.loadDeadlineList();
setupRecyclerView(recyclerView);
return view;
}
@Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(false);
RecyclerView recyclerView = view.findViewById(R.id.deadline_recyclerview);
TextView textView = view.findViewById(R.id.deadline_empty_text);
if (deadlineList.isEmpty()) {
recyclerView.setVisibility(GONE);
textView.setVisibility(View.VISIBLE);
} else {
recyclerView.setVisibility(View.VISIBLE);
textView.setVisibility(GONE);
}
}
}
由于这里的RecyclerView放在了SwipeRefreshLayout中,因此Fragment实现了对应的OnRefreshListener,也有了对应函数OnRefresh,就把检查列表是否为空的操作放进了OnRefresh里(程序启动的时候会自动调用一次的,不需要手动调用)。
另外不能直接把RecyclerView和TextView并排放在SwipeRefreshLayout中,会出现问题,我的做法是用一个LinearLayout把它们两个包起来再放进去,xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/deadline_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/deadline_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<TextView
android:id="@+id/deadline_empty_text"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/deadline_empty_text"
android:visibility="visible" />
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>