微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

android – RecyclerView添加EmptyView

我正在尝试在我的RecyclerView适配器上实现一个EmptyView,但我没有得到任何结果.

我跟着这个tutorialtip,但没有人为我工作.

我实施了:

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,false);
ViewHolder vh = new ViewHolder(v);
return vh;

但它不允许我编译,因为它们是不同的ViewHolder,因为我创建了两个ViewHolder类,但它们扩展了Recycler.ViewHolder,所以我没有得到它…

我正在尝试这样做,因为我有一个SearchView,我希望当列表为空时它显示一个EmptyView,我已经让它以编程方式进行,但我更喜欢添加像布局,因为我不知道很多如何以编程方式放置TextViews和Buttons.

如果我放

return dataList.size() > 0 ? dataList.size() : 1;

它给了我错误,因为索引是0.

我已经调试了viewType并且始终为1,那么它将不会加入if条件…

深入Android我发现了这个:

/**
 * Return the view type of the item at <code>position</code> for the purposes
 * of view recycling.
 *
 * <p>The default implementation of this method returns 0,making the assumption of
 * a single view type for the adapter. Unlike ListView adapters,types need not
 * be contiguous. Consider using id resources to uniquely identify item view types.
 *
 * @param position position to query
 * @return integer value identifying the type of the view needed to represent the item at
 *                 <code>position</code>. Type codes need not be contiguous.
 */
 public int getItemViewType(int position) {
    return 0;
 }

但问题是没有改变价值.

编辑

我几乎完成了,我这样做了:

@Override
public int getItemViewType(int position) {

    return list.size() > 0 ? list.size() : 1;
}

但有时当size()为0时它会返回0 …我没有得到它,我正在使用这个SearchView,有时当我输入一个与列表中的任何项目都不匹配的字母时它没有显示,有时它…

另外发生的事情是,当我把它放在屏幕左侧时,它会显示在屏幕的左侧,但是我觉得这是RecyclerView的问题,因为布局放在它里面.

RecyclerView布局:

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:id="@+id/rtpew"
    android:layout_centerInParent="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    >
         <LinearLayout android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/linearpew">
            <android.support.v7.widget.RecyclerView
             android:id="@+id/rv"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
            />
         </LinearLayout>
 </RelativeLayout>

这是我的空行布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true">
<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ImageViewSearchFail"
    android:src="@drawable/sadface"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true" />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:layout_gravity="center"
    android:textSize="@dimen/15dp"
    android:layout_marginTop="4dp"
    android:text="foo"
    android:layout_below="@+id/ImageViewSearchFail"
    android:layout_centerHorizontal="true" />
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ButtonAddEntity"
    android:text="foo"
    android:background="?android:selectableItemBackground"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />
</RelativeLayout>

我想的另一种方式是以编程方式实现它如下:

@Override
public boolean onQueryTextChange(String query) {
    final ArrayList<List> filteredModelList = filter(mModel,query);
        mAdapter.animateto(filteredModelList);
        rv.scrollToPosition(0);
    if(query.isEmpty()){
            //Here
    }
  return true;
}

而且:

private ArrayList<List> filter(ArrayList<List> models,String query) {
    query = query.toLowerCase();
    final ArrayList<List> filteredModelList = new ArrayList<List>();
    for (List model : models) {
        final String text = model.getRedname().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    if (filteredModelList.size()<0) {
           //HERE
    }
    else{
           //Delete the views added
    }
    return filteredModelList;
}

问题

– 我只使用@Jimeux answer添加视图,但我想在适配器上执行此操作,我得到了它,但即使列表为空,也不总是显示视图.

– 是时候把它放在RecyclerView里面的emptyview.xml,然后我将所有这个xml放在右边显示的中心.我试图以编程方式添加xml但它就像一个混乱….

解决方法

由于您需要处理两种不同类型的视图,因此使用业务对象的中间列表更容易将它们更容易地与视图绑定.想法是在列表中有一种占位符来表示空状态.从这个意义上讲,定义中间层非常有用,可以让您考虑将来应用于列表的最终更改(例如,添加元素类型).此外,通过这种方式,您可以更清楚地将业务模型与ui表示分离(例如,您可以实现基于模型对象的内部状态返回ui设置的方法).

您可以按以下步骤操作:

>为列表项(例如ListItem)定义专用抽象类型以包装业务对象.它的实现可能是这样的:

public abstract class ListItem {

    public static final int TYPE_EMPTY = 0;
    public static final int TYPE_MY_OBJ = 1;

    abstract public int getType();

}

>为每个List元素类型定义一个类:

public class EmptyItem extends ListItem {

    @Override
    public int getType() {
        return TYPE_EMPTY;
    }

}

public class MyObjItem extends ListItem {

    private MyObj obj;

    public ContactItem(MyObj obj) {
        this.obj = obj;
    }

    public MyObj getMyObj() {
        return obj;
    }

    // here you can also add methods for simplify
    // objects rendering (e.g. get background color
    // based on your object internal status)

    @Override
    public int getType() {
        return TYPE_MY_OBJ;
    }

}

>创建列表.

List<ListItem> mItems = new ArrayList<>();
if (dataList != null && dataList.size() > 0) {
    for (MyObj obj : dataList) {
        mItems.add(new MyObjItem(obj));
    }
} else {
    mItems.add(new EmptyItem());
}

这是代码中最重要的部分.您可以使用许多选项来创建此列表.您可以在RecyclerView适配器内部或外部执行此操作,但正确处理对其的最终修改非常重要.这对于利用适配器通知方法至关重要.例如,如果在适配器中创建列表,则应该提供添加删除模型项的方法.例如:

public void addobj(MyObj obj) {
    if (mItems.size() == 1 && mItems.get(0).getType() == ListItem.EMPTY_TYPE) {
        mItems.clear();
    }
    mItems.add(new MyObjItem(obj));
    notifyDataSetChanged();
}

>为RecyclerView定义适配器,处理在第3点定义的List.重要的是重写getItemViewType方法,如下所示:

@Override
public int getItemViewType(int position) {
    return mItems.get(position).getType();
}

此外,ViewHolder的类型应该是RecyclerView.ViewHolder(除非你决定在这种情况下创建一个中间类).

>那么你需要有两个布局和ViewHolder用于空和商业对象项目.适配器方法应该相应地处理:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
    if (viewType == ListItem.TYPE_EMPTY) {
        View itemView = mLayoutInflater.inflate(R.layout.empty_layout,false);
        return new EmptyViewHolder(itemView);
    } else {
        View itemView = mLayoutInflater.inflate(R.layout.myobj_layout,false);
        return new MyObjViewHolder(itemView);
    }
}


@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder,final int position) {
    int type = getItemViewType(position);
    if (type == ListItem.TYPE_EMPTY) {
        EmptyItem header = (EmptyItem) mItems.get(position);
        EmptyViewHolder holder = (EmptyViewHolder) viewHolder;
        // your logic here... probably nothing to do since it's empty
    } else {            
        MyObjItem event = (MyObjItem) mItems.get(position);
        MyObjViewHolder holder = (MyObjViewHolder) viewHolder;
        // your logic here
    }
}

当然,正如我在开头所写的那样,您不需要为ui表示(EmptyItem和MyObjItem)严格定义中间类型.您甚至可以使用MyObj类型并为其创建表示空占位符的特定配置.这种方法可能不是最好的,以防您将来需要通过包含新的列表项类型来使您的逻辑更复杂.

原文地址:https://www.jb51.cc/android/308843.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐