listview to recyclerview:如何实现2个可能的视图?

时间:2018-01-12 23:05:33

标签: android android-recyclerview recycler-adapter

在我的Listview中,此代码有效:

    for (int number = 0; number < matchingContacts.size(); number++) {

        //if a phone number is in our array of matching contacts
        if (matchingContacts.contains(selectPhoneContact.getPhone()))

        {
            //if a matching contact, no need to show the Invite button
            viewHolder.invite.setVisibility(View.GONE);

            //once a matching contact is found, no need to keep looping x number of time, move onto next contact
            break;

        } else {
            //if not a matching contact, no need to show the check box
            viewHolder.check.setVisibility(View.GONE);

        }

    }

如果matching arraylist中有电话号码,那么它应该invite button不可见,如果它不在matching arraylist中,它应该使checkbox不可见。

但不在我的recyclerview中,我试图让代码工作。

在第一次加载时它看起来没问题,但是一旦你开始滚动视图就搞砸了 - 复选框和按钮出现在他们不应该的地方。

我已经在Recyclerview中看到你应该用case statements来实现这个,我在这里看Why RecyclerView items disappear with scrollingHow to create RecyclerView with multiple view type?但是对于我的生活,我无法得到它工作!

你能帮忙吗?

这是我的代码:

public class PopulistoContactsAdapter extends RecyclerView.Adapter<PopulistoContactsAdapter.ViewHolder> {

    //make a List containing info about SelectPhoneContact objects
    public List<SelectPhoneContact> theContactsList;

    Context context_type;

    ArrayList<String> matchingContacts = new ArrayList<String>();

    public static class ViewHolder extends RecyclerView.ViewHolder {

        //In each recycler_blueprint show the items you want to have appearing
        public TextView title, phone;
        public CheckBox check;
        public Button invite;


        public ViewHolder(final View itemView) {
            super(itemView);
            //title is cast to the name id, in recycler_blueprint,
            //phone is cast to the id called no etc
            title = (TextView) itemView.findViewById(R.id.name);
            phone = (TextView) itemView.findViewById(R.id.no);
            invite = (Button) itemView.findViewById(R.id.btnInvite);
            check = (CheckBox) itemView.findViewById(R.id.checkBoxContact);

        }

    }

    public PopulistoContactsAdapter(List<SelectPhoneContact> selectPhoneContacts, Context context, int activity) {

        theContactsList = selectPhoneContacts;
        context_type = context;

        matchingContacts.add("+3531234567");
        matchingContacts.add("+3536789012");
        matchingContacts.add("+3530987654");
        matchingContacts.add("+3538765432");

    }

    @Override
    public PopulistoContactsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View contactView = inflater.inflate(R.layout.recycler_blueprint, parent, false);
        ViewHolder viewHolder = new ViewHolder(contactView);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final PopulistoContactsAdapter.ViewHolder viewHolder, final int position) {
        //bind the views into the ViewHolder
        //selectPhoneContact is an instance of the SelectPhoneContact class.
        //We will assign each row of the recyclerview to contain details of selectPhoneContact:

        //The number of rows will match the number of contacts in our contacts list
        final SelectPhoneContact selectPhoneContact = theContactsList.get(position);

        //a text view for the name, set it to the matching selectPhoneContact
        TextView title = viewHolder.title;
        title.setText(selectPhoneContact.getName());

        //a text view for the number, set it to the matching selectPhoneContact
        TextView phone = viewHolder.phone;
        phone.setText(selectPhoneContact.getPhone());

        Button invite = viewHolder.invite;

        CheckBox check = viewHolder.check;

        for (int number = 0; number < matchingContacts.size(); number++) {

            //if a phone number is in our array of matching contacts
            if (matchingContacts.contains(selectPhoneContact.getPhone()))

            {
                //if a matching contact, no need to show the Invite button
                viewHolder.invite.setVisibility(View.GONE);
                //once a matching contact is found, no need to keep looping x number of time, move onto next contact
                break;

            } else {
                //if not a matching contact, no need to show the check box
                viewHolder.check.setVisibility(View.GONE);

            }

        }

    }

    @Override
    public int getItemCount() {

        return theContactsList.size();
    }
}

2 个答案:

答案 0 :(得分:1)

RecyclerView可以处理具有不同视图持有者的多种视图类型。

首先,您必须覆盖适配器上的getItemViewType(int position)方法,该方法将根据其位置返回对象的类型。然后为每种视图类型创建视图持有者类。

考虑视图类型处理onCreateViewHolder(ViewGroup parent, int viewType)方法:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == YOUR_FIRST_TYPE) {
        //inflate first type of view
        return new FirstTypeViewHolder(view);
    } else if (viewType == YOUR_SECOND_TYPE) {
        //inflate second type of view
        return new SecondTypeViewHolder(view);
    }
}

考虑视图类型处理onBindViewHolder(ViewHolder viewHolder, int position)

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
    int viewType = getItemViewType(position);

    if (viewType == YOUR_FIRST_TYPE) {
        FirstTypeViewHolder firstTypeViewHolder = (FirstTypeViewHolder) viewHolder;
        //do your stuff
    } else if (viewType == YOUR_SECOND_TYPE) {
        SecondTypeViewHolder secondTypeViewHolder = (SecondTypeViewHolder) viewHolder;
        //do your stuff
    }
}

您可以查看此tutorial

答案 1 :(得分:1)

方法1:实际上在您的情况下,不需要使用多种View类型。这可能是一种更简单的方法。相反,我建议您修改SelectPhoneContact类以包含一个简单的布尔字段(可能称为isMatching),用于标记此电话号码是否为匹配的联系人。然后,您可以创建一个简单的setter和getter方法,如setIsMatchingContact(boolean)isMatchingContact()来更新/读取此标志。

当您初始化列表并添加SelectPhoneContact时,请通过设置setIsMatchingContact(boolean)方法进行预处理,以确定哪些实例属于或不属于匹配的联系人。在onBindViewHolder方法中,您只需检查matchingContacts并相应地更改可见性,而不是迭代selectPhoneContact.isMatchingContact()。这也更有效,因为您不必执行在绑定方法中迭代大型列表的潜在昂贵操作,这可能导致滚动结果并出现问题。

如果您的matchingContacts列表随时间发生变化,您可以随时编写一个循环遍历SelectPhoneContact列表并重置isMatching布尔值的方法。

方法2:如果您不想扩展您的SelectPhoneContact类以使用我提到的这两种方法,您可以创建一个私有静态包装类,如下所示:

private static class SelectPhoneContactItem {
    SelectPhoneContact selectPhoneContact;
    boolean isMatching;
}

然后将其用作适配器中的主要列表:

public List<SelectPhoneContactItem> theContactsList;

与方法1类似,您应该预先处理SelectPhoneContactItemmatchingContacts所在的isMatching并根据需要分配<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" /> </dependentAssembly> </assemblyBinding> 布尔值。

除非存在一些设计约束,否则您应该使用方法1。如果我的答案有意义,请告诉我,希望这有帮助!