首页 文章

Android:如何切换RecyclerView列表的布局?

提问于
浏览
1

我有一个默认布局,在RecyclerView列表中包含一堆空白CardView,基本上是一个欢迎屏幕,供用户向他们展示CardViews的外观 . 然后,用户启动某些数据的输入屏幕,然后单击“保存”按钮将数据保存到CardView中 . 用户单击“保存”后,布局应从具有空白CardView的默认布局更改为包含用户数据的新单个CardView . 之后,如果用户删除了所有的CardView,则视图应切换回默认的空白CardView .

我正在努力解决如何在onCreateViewHolder中设置适配器的代码,因为getItemCount()已经具有默认的正值(因为RecyclerView列表中已经有4或5个空白的CardViews),这将在以后发生冲突一旦用户创建4或5个CardView,就会获得相同的getItemCount()数量 . 有关如何设置默认布局然后切换到新布局的任何想法,如果列表清空了用户创建的CardView,则可以恢复到默认布局?

下面是我在适配器中为两个布局进行测试的失败尝试 . 我意识到它不起作用,因为默认布局从未有过零的ItemCount,因为已经有4或5个空白CardView:

...
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {

private List<ContactInfo> contactList;

public ContactAdapter(List<ContactInfo> contactList) {
    this.contactList = contactList;
}

@Override
public int getItemCount() {
    return contactList.size();
}

@Override
public ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    if(contactList.size()== 0) {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.defaultcard_layout, viewGroup, false);
        return new ContactViewHolder(itemView);
    }
    else {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.singlecard_layout, viewGroup, false);
        return new ContactViewHolder(itemView);
    }
}

修改了Adapter和removeItem代码:

...
private LayoutInflater mLayoutInflater;
private List<Contact> mContacts;
private OnItemTapListener mOnItemTapListener;

public ListContactsAdapter(Context context, List<Contact> contacts) {
    Context mContext;
    mContext = context;
    mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mContacts = contacts;
}

public void removeItem(Contact contact, int position) {
    mContacts.remove(contact);
    if (mContacts.size()==0) {
        // if no more contacts in list,
        // we rebuild from scratch
        mContacts.clear();
        notifyDataSetChanged();
    } else {
        // else we just need to remove
        // one item
        mContacts.remove(position);
        notifyItemRemoved(position);
    }
}

1 回答

  • 2

    这是您可以遵循的方法:

    • 为List项(例如ListItem)定义专用的抽象类型以包装业务对象 . 它的实现可能是这样的:
    public abstract class ListItem {
    
        public static final int TYPE_EMPTY = 0;
        public static final int TYPE_CONTACT = 1;
    
        abstract public int getType();
    }
    
    • 为每个List元素类型定义一个类:
    public class EmptyItem {
    
        @Override
        public int getType() {
            return TYPE_EMPTY;
        }
    
    }
    
    public class ContactItem {
    
        private ContactInfo contact;
    
        // here getters and setters 
        // for title and so on, built 
        // using contact
    
        public ContactItem(ContactInfo info) {
            this.contact = info;
        }
    
        @Override
        public int getType() {
            return TYPE_CONTACT;
        }
    
    }
    
    • 创建列表 . 在下面的逻辑中,我只是确保你总是至少有5个元素 . 如果您的联系人少于5个,将显示空白布局 . 每次从外部Activity修改contactList时,即使在mContactList中也可以进行此类修改,因为适配器保留对Activity中管理的相同List的引用(请参阅适配器构造函数) . 例如,在您需要调用 updateContactList 方法更新UI之后添加新联系人 .
    List<ContactInfo> mContactList;
    List<ListItem> mItems;
    
    public ContactsAdapter(List<ContactInfo> contactList) {
        mContactList = contactList;
        mItems = buildContactsList(mContactList);       
    }
    
    // Method for building ui list.
    private List<ContactItem> buildContactsList(List<ContactInfo> contactList) {
        List<ContactItem> list = new ArrayList<>();
        for (ContactInfo contact : contactList) {
            list.add(ContactItem(contact));
        }
        if (list.size() < 5) {
            for (int i=list.size(); i<5; i++) {
                list.add(EmptyItem());
            }
        }
    }
    
    // Method for updating contact list, providing
    // a new one. Everything to be build from scratch.
    public void updateContactsList() {
        mItems.clear();
        mItems.addAll(buildContactsList(mContactList));
        notifyDataSetChanged();
    }
    
    • 为RecyclerView定义适配器,处理在第3点定义的List . 重要的是重写getItemViewType方法,如下所示:
    @Override
    public int getItemViewType(int position) {
        return mItems.get(position).getType();
    }
    

    然后你需要有两个布局和ViewHolder用于空和联系项目 . 适配器方法应该相应地处理:

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ListItem.TYPE_EMPTY) {
            View itemView = mLayoutInflater.inflate(R.layout.defaultcard_layout, parent, false);
            return new EmptyViewHolder(itemView);
        } else {
            View itemView = mLayoutInflater.inflate(R.layout.singlecard_layout, parent, false);
            return new ContactViewHolder(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 {            
            ContactItem event = (ContactItem) mItems.get(position);
            ContactViewHolder holder = (ContactViewHolder) viewHolder;
            // your logic here
        }
    }
    

    如果在 contactList 上进行更新,您当然应该通过清理它来更新 mItems ,再次使用在第3点报告的相同逻辑填充它,然后在适配器上使用notifyDataSetChanged .

相关问题