问题
I have a default layout that holds a bunch of blank CardViews in a RecyclerView list, basically a welcome screen for the user to show them what CardViews look like. The user then launches an input screen for some data and clicks a "Save" button to save the data into a CardView. Once the user clicks Save, the layout should change from the default layout with the blank CardViews to the new, single CardView that contains the user data. Later, if the user deletes all of their CardViews, then the view should switch back to the default blank CardViews.
I'm struggling with how to set the code int the Adapter in the onCreateViewHolder because getItemCount() will already have a positive value for the default (because the RecyclerView list will already have 4 or 5 blank CardViews in it) which would conflict later with the same getItemCount() amount once the user creates 4 or 5 CardViews. Any ideas on how to set a default layout and then switch to a new layout that can then revert back to the default layout if the list is emptied of user-created CardViews?
Below is my failed attempt at laying out a test for two layouts in the Adapter. I realized it would not work because the default layout never had an ItemCount of zero since there are already 4 or 5 blank CardViews:
...
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);
}
}
revised Adapter and removeItem code:
...
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:
This is approach you could follow:
Define a dedicated abstract type for List items (e.g. ListItem) to wrap your business objects. Its implementation could be something like this:
public abstract class ListItem { public static final int TYPE_EMPTY = 0; public static final int TYPE_CONTACT = 1; abstract public int getType(); }
Define a class for each of your List element type:
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; } }
Create your list. In logic below I'm just ensuring you will always have at least 5 elements. In case you have less than 5 contacts, empty layout will be displayed. Every time you modify your contactList from the outside Activity, such modification will be available even in mContactList because the adapter keeps a reference to the same List managed in the Activity (see Adapter constructor). In case for example you add a new contact, after you just need to invoke
updateContactList
method for having your UI updated.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(); }
Define an adapter for your RecyclerView, working on List defined at point 3. Here what is important is to override getItemViewType method as follows:
@Override public int getItemViewType(int position) { return mItems.get(position).getType(); }
Then you need to have two layouts and ViewHolder for empty and contact items. Adapter methods should take care of this accordingly:
@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 } }
In case of updates on contactList
you should of course update mItems
accordingly by cleaning it, filling it again with same logic reported at point 3 and then notifyDataSetChanged on the Adapter.
来源:https://stackoverflow.com/questions/34936863/android-how-do-i-switch-layouts-for-a-recyclerview-list