繁体   English   中英

搜索过滤器后 Recyclerview 行格式更改

[英]Recyclerview row format changes after search filter

我有一个显示联系人列表的回收视图。 为了区分同时也是我的应用程序用户的联系人(我们将这些称为应用程序联系人)和所有其他联系人(非应用程序联系人),我将所有应用程序联系人的字体设为粗体(Typeface.BOLD),和非应用程序联系人正常(Typeface.NORMAL)。 但是,如果在搜索联系人时过滤了 recyclerview,并且应用程序联系人以粗体显示在某些行(比如第 1 行和第 2 行)中,那么这些行将保留为粗体。 即使当我更改搜索时,非应用程序联系人(应该是普通字体)现在占据了那些行(1 和 2),它是粗体。 基本上第 1 行和第 2 行现在保留为粗体,无论其中显示的联系人类型如何。

这是我的 recyclerview 适配器。 onBindViewHolder 是我更改字体的地方。 “is Suma Contact” boolean 表示该联系人是应用程序联系人。


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

    private Context context;
    private List<RecipientsContactItem> contactItems;
    private final int SELECT_DROPOFF_REQUEST_CODE = 77;

    public SearchRecipientHintsAdapter (Context context, List<RecipientsContactItem> contactItems) {
        this.context = context;
        this.contactItems = contactItems;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipients_contact_row,parent,false);
        return new ViewHolder(view, context);
    }

    @Override
    public void onBindViewHolder(@NonNull SearchRecipientHintsAdapter.ViewHolder holder, int position) {
        RecipientsContactItem contactItem = contactItems.get(position);
        holder.name.setText(contactItem.getName());
        holder.phoneNumber.setText(contactItem.getPhoneNumber());

        if (contactItem.getImage() != null && !contactItem.getImage().isEmpty()) {
            try {
                Picasso.get().load(contactItem.getImage()).into(holder.image);
            } catch (Throwable ignored) { }
        } else {
            holder.image.setImageDrawable(context.getResources().getDrawable(R.drawable.user_default_img));
        }

        if (contactItem.isVerified()) {
            holder.verificationIcon.setVisibility(View.VISIBLE);
        } else {
            holder.verificationIcon.setVisibility(View.GONE);
        }

        if (contactItem.isSumaContact()) {

            holder.name.setTypeface(holder.name.getTypeface(), Typeface.BOLD);

            switch (contactItem.getPrivacy()) {
                case "Public":
                    holder.publicIcon.setVisibility(View.VISIBLE);
                    holder.privateIcon.setVisibility(View.GONE);
                    holder.allowedIcon.setVisibility(View.GONE);
                    holder.inviteButton.setVisibility(View.GONE);
                    break;
                case "Private":
                    holder.publicIcon.setVisibility(View.GONE);
                    holder.privateIcon.setVisibility(View.VISIBLE);
                    holder.allowedIcon.setVisibility(View.GONE);
                    holder.inviteButton.setVisibility(View.GONE);
                    break;
                case "Allowed":
                    holder.publicIcon.setVisibility(View.GONE);
                    holder.privateIcon.setVisibility(View.GONE);
                    holder.allowedIcon.setVisibility(View.VISIBLE);
                    holder.inviteButton.setVisibility(View.GONE);
                    break;
            }
        } else {
            holder.name.setTypeface(holder.name.getTypeface(), Typeface.NORMAL);
            holder.inviteButton.setVisibility(View.VISIBLE);
            holder.publicIcon.setVisibility(View.GONE);
            holder.privateIcon.setVisibility(View.GONE);
            holder.allowedIcon.setVisibility(View.GONE);
        }
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        private TextView name;
        private TextView phoneNumber;
        private ImageView image;
        private ImageView verificationIcon;
        private Button inviteButton;
        private ImageView publicIcon;
        private ImageView privateIcon;
        private ImageView allowedIcon;

        public ViewHolder(@NonNull View itemView, Context ctx) {
            super(itemView);
            context = ctx;
            name = itemView.findViewById(R.id.recipientsCRowNameID);
            phoneNumber = itemView.findViewById(R.id.recipientsCRowPhoneID);
            image = itemView.findViewById(R.id.recipientsCRowImageID);
            verificationIcon = itemView.findViewById(R.id.recipientsCRowVerifiedID);
            inviteButton = itemView.findViewById(R.id.recipientsCRowInviteID);
            publicIcon = itemView.findViewById(R.id.recipientsCRowPublicID);
            privateIcon = itemView.findViewById(R.id.recipientsCRowPrivateID);
            allowedIcon = itemView.findViewById(R.id.recipientsCRowAllowedID);

            itemView.setOnClickListener(v -> {
                //Get position of row
                int position = getAdapterPosition();

                RecipientsContactItem contactItem = contactItems.get(position);
                String uID = contactItem.getUID();
                String name = contactItem.getName();
                String phoneNumber = contactItem.getPhoneNumber();
                String lat = contactItem.getLat();
                String lng = contactItem.getLng();
                boolean isSumaContact = contactItem.isSumaContact();

               if (isSumaContact) {
                   if (contactItem.getPrivacy().equals("Public") || contactItem.getPrivacy().equals("Allowed")) {
                       Intent returnRecipientIntent = ((Activity) context).getIntent();
                       returnRecipientIntent.putExtra("uID", uID);
                       returnRecipientIntent.putExtra("name", name);
                       returnRecipientIntent.putExtra("phoneNumber", phoneNumber);
                       returnRecipientIntent.putExtra("lat", lat);
                       returnRecipientIntent.putExtra("lng", lng);
                       returnRecipientIntent.putExtra("isSumaContact", true);

                       ((Activity) context).setResult(Activity.RESULT_OK, returnRecipientIntent);
                       ((Activity) context).finish();
                   } else {
                       Toast.makeText(context, R.string.recipients_search_disallowed_toast, Toast.LENGTH_LONG).show();
                   }
               } else {
                   Intent dropOffSearchIntent = new Intent(context, SelectDropoff.class);
                   ((Activity) context).startActivityForResult(dropOffSearchIntent, SELECT_DROPOFF_REQUEST_CODE);
               }
            });

            inviteButton.setOnClickListener(view -> {
                Intent sendInvite = new Intent(android.content.Intent.ACTION_VIEW);
                sendInvite.putExtra("address", contactItems.get(getAdapterPosition()).getPhoneNumber());
                sendInvite.putExtra("sms_body", context.getResources().getString(R.string.recipients_invite_link));
                sendInvite.setType("vnd.android-dir/mms-sms");
                try {
                    context.startActivity(sendInvite);
                } catch (Throwable t) {
                    Toast.makeText(context, "Sorry, invite not working. Please use the invite in your main menu", Toast.LENGTH_LONG).show();
                }
            });
        }
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    public void updateWithSearchFilter (List<RecipientsContactItem> newList) {
        contactItems = new LinkedList<>();
        contactItems.addAll(newList);
        notifyDataSetChanged();
    }
}

这是 setOnQueryTextListener() 中的 onQueryTextChange() ,我在这里过滤搜索并将结果/新列表传递给上面的适配器

            public boolean onQueryTextChange(String newText) {
                
                String userInput = newText.toLowerCase();
                if (userInput.startsWith("0")) {userInput = userInput.substring(1);}


                List<RecipientsContactItem> newList = new LinkedList<>();

                for (RecipientsContactItem contactItem : sumaContacts) {
                    if (contactItem.getName().toLowerCase().contains(userInput) || contactItem.getPhoneNumber().contains(userInput)) {
                        newList.add(contactItem);
                    }
                }
                ((SearchRecipientHintsAdapter) searchRHintsAdapter).updateWithSearchFilter(newList);
                return true;
            }

镜头 1:显示的 2 个联系人是非应用程序联系人,所以他们的字体是正常的(不是粗体)

镜头 2. 过滤搜索后显示应用程序联系人:第一个联系人是联系人(粗体),第二个是非应用程序联系人(普通字体 - 非粗体)

镜头 3. 清除搜索过滤器以显示镜头 1 中的联系人后:两个联系人都是非应用程序联系人,应使用普通字体(不是粗体)。 但是第一个联系人显示为粗体,因为在过滤搜索时,应用程序联系人(粗体)曾短暂地显示在那里(在镜头 2 中)

注意:这个问题过去也是由滚动引起的。 直到我 @Override 适配器的 getItemViewType() 方法

最初,每当我滚动 recyclerview 时,粗体字体都会错误地应用于不应该是粗体的行/联系人。 直到我找到一个解决方案,我不得不像这样覆盖 recyclerview 适配器的 getItemViewType() 方法:

@Override
    public int getItemViewType(int position) {
        return position;
    }

然后它被固定(用于滚动)。 直到我意识到过滤问题仍然存在。 所以这就是我现在要解决的问题

问题是

holder.name.setTypeface(holder.name.getTypeface(), Typeface.NORMAL);

当重新绑定一个带有粗体的 viewholder 时, holder.getTypeface()返回之前的粗体字体。 现在, Typeface.NORMAL的值为0 这是来自cs.android.comsetTypeface()实现:

public void setTypeface(@Nullable Typeface tf, @Typeface.Style int style) {
    if (style > 0) {
        if (tf == null) {
            tf = Typeface.defaultFromStyle(style);
        } else {
            tf = Typeface.create(tf, style);
        }

        setTypeface(tf);
        // now compute what (if any) algorithmic styling is needed
        int typefaceStyle = tf != null ? tf.getStyle() : 0;
        int need = style & ~typefaceStyle;
        mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
        mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
    } else {
        mTextPaint.setFakeBoldText(false);
        mTextPaint.setTextSkewX(0);
        setTypeface(tf);
    }
}

注意那里的if (style > 0)部分。 因此,传入Typeface.NORMAL将按原样设置字体,而不对其进行任何样式设置,因此您的粗体样式将保持粗体。

要解决此问题,请传入null作为适合您的字体,或者将字体重置为适合您需要的默认值。

另外,你的性能也有问题

@Override
public int getItemViewType(int position) {
    return position;
}

这使得每一行都有自己特定的视图类型。 但是您实际上只有一种视图类型,因此根本不需要重写此方法。 或者,如果这样做,您可以返回一个常量值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM