Android Linkify.addLinks() 适用于一个 textview 而不是另一个

Posted

技术标签:

【中文标题】Android Linkify.addLinks() 适用于一个 textview 而不是另一个【英文标题】:Android Linkify.addLinks() works for one textview and not the other one 【发布时间】:2020-04-18 15:16:01 【问题描述】:

我有一个聊天实现,类似于我的应用中的 whatsapp。

在聊天中,我有一个接收者状态和一个发送者状态。

我面临的问题是,在发件人状态下,我发送的链接根本不可点击,尽管我对它们都执行了完全相同的代码。

这是我对待发件人视图持有者的方式 -

private void handleMessageForSender(Message item, TxtViewHolder txtViewHolder, String time, String msg) 
        txtViewHolder.getViewSender().setVisibility(View.VISIBLE);
        txtViewHolder.getTxtChatTime().setText(time);
        txtViewHolder.getTxtChatTime().setTextColor(context.getResources()
                .getColor(R.color.color_black));
        txtViewHolder.getTxtChatTime().setVisibility(View.VISIBLE);
        txtViewHolder.getTxtChatSender().setTextColor(context.getResources()
                .getColor(R.color.color_black));

        boolean oneRowWithLink = false;

        Matcher matcher = android.util.Patterns.WEB_URL.matcher(messageDetail.getMessage() != null && (item.getRecall() == null || !item.getRecall()) && messageDetail.getMessage().contains("http") ? messageDetail.getMessage() : "");
        if (matcher.find()) 
            oneRowWithLink = true;
            String urlMessage = matcher.group(1);
            LinkPreviewModel linkPreviewModel = linkPreviewModelHashMap.get(urlMessage);
            if (linkPreviewModel != null) 
                txtViewHolder.getViewSender().setPadding(0, 0, 0, 4);
                txtViewHolder.getLinkSentLayout().setVisibility(View.VISIBLE);
                txtViewHolder.getLinkTitle().setText(linkPreviewModel.getTitle());
                txtViewHolder.getLinkTitle().setTypeface(null, Typeface.BOLD);
                txtViewHolder.getLinkMainUrl().setText(linkPreviewModel.getLinkMainUrl());

                if (linkPreviewModel.getImageUrl() != null && linkPreviewModel.getImageUrl().length() > 0) 
                    linkPreviewModelPositionsMap.put(item.getMid(), linkPreviewModel.getImageUrl());
                    MediaUtils.loadImageWithGlide(context, linkPreviewModel.getImageUrl(),
                            txtViewHolder.getLinkImageUrl(), R.drawable.ic_image_placeholder);
                 else 
                    txtViewHolder.getLinkImageUrl().setVisibility(View.GONE);
                

                if (linkPreviewModel.getDescription() != null && linkPreviewModel.getDescription().length() > 0) 
                    txtViewHolder.getLinkDescription().setVisibility(View.VISIBLE);
                    txtViewHolder.getLinkDescription().setText(linkPreviewModel.getDescription());
                 else 
                    txtViewHolder.getLinkDescription().setVisibility(View.GONE);
                

             else 
                txtViewHolder.getLinkSentLayout().setVisibility(View.GONE);
                parseLink(urlMessage);
            
         else 
            txtViewHolder.getLinkSentLayout().setVisibility(View.GONE);
            txtViewHolder.getViewSender().setPadding(4, 4, 4, 4);
        

        if (item.getRecall() != null && item.getRecall()) 
            displayRecallInfo(item, txtViewHolder);
         else 
            txtViewHolder.getImgChatStatus().setVisibility(View.VISIBLE);
            txtViewHolder.getSentRecallImage().setVisibility(View.GONE);
            txtViewHolder.getTxtChatSender().setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
            txtViewHolder.getTxtChatSender().setTextKeepState(gethtmlChatMessageText(msg));
            Linkify.addLinks(txtViewHolder.getTxtChatReceiver(), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS);
            chatMessageUtils.setRecentChatStatus(txtViewHolder.getImgChatStatus(), item.getStatus());
            new TextReplyViewUtils().showSenderReplyWindow(txtViewHolder, item, context);

            txtViewHolder.getTxtChatSender().measure(0, 0);
            if (!oneRowWithLink && txtViewHolder.getTxtChatSender().getMeasuredWidth() < (SCREEN_WIDTH * 70) / 100 && txtViewHolder.getTxtChatSender().getLineCount() == 1 && TextUtils.isEmpty(item.getReplyTo())) 
                //set time layout new parameters
                txtViewHolder.getSenderTimeLayout().measure(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
                txtViewHolder.getImageStar().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

                if (defaultViewSendTimeWidth == -1) 
                    defaultViewSendTimeWidth = txtViewHolder.getSenderTimeLayout().getMeasuredWidth();
                

                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
                params.gravity = Gravity.BOTTOM | Gravity.END;
                params.topMargin = isHighResolutionHeight ? 25 : 15;
                txtViewHolder.getSenderTimeLayout().setLayoutParams(params);

                int fixedWidth = (item.getFavourite() != null && item.getFavourite()) ? txtViewHolder.getSenderTimeLayout().getMeasuredWidth() : defaultViewSendTimeWidth - 20;
                LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(txtViewHolder.getTxtChatSender().getMeasuredWidth() + fixedWidth,
                        LinearLayout.LayoutParams.WRAP_CONTENT);
                txtViewHolder.getTxtChatSender().setLayoutParams(params1);

                // if one row, set always in left
                txtViewHolder.getTxtChatSender().setGravity(Gravity.LEFT);


                //reduce margin bottom to txt view(because space..)
                FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
                        FrameLayout.LayoutParams.WRAP_CONTENT);
                params2.bottomMargin = isHighResolutionHeight ? -60 : -30;
                txtViewHolder.getViewSendLayout().setLayoutParams(params2);
             else 
            // need this code because it is view holder that reuse layouts

                //return time layout to basic parameters
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
                params.gravity = Gravity.BOTTOM | Gravity.END;
                txtViewHolder.getSenderTimeLayout().setLayoutParams(params);

                //return chat text view to basic parameters
                LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(TextUtils.isEmpty(item.getReplyTo()) ? LinearLayout.LayoutParams.WRAP_CONTENT :
                        LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                txtViewHolder.getTxtChatSender().setLayoutParams(params1);

                if (checkRtl(txtViewHolder.getTxtChatSender().getText().toString())) 
                    txtViewHolder.getTxtChatSender().setGravity(Gravity.RIGHT);
                 else 
                    txtViewHolder.getTxtChatSender().setGravity(Gravity.LEFT);
                


                //return view receive to basic parameters
                FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
                        FrameLayout.LayoutParams.WRAP_CONTENT);
                txtViewHolder.getViewSendLayout().setLayoutParams(params2);

            

            if (forwardUtils.isSendForwardUtils(userJID, messageDetail.getCreatedBy(), item.getGroupChatSender() != null && item.getGroupChatSender().length() > 0
                    ? item.getGroupChatSender() : item.getChatUser()))
                txtViewHolder.getForwardSendLayout().setVisibility(View.VISIBLE);
            else
                txtViewHolder.getForwardSendLayout().setVisibility(View.GONE);
        
    

这是我对待接收者状态的方式 -

private void handleMessageForReceiver(Message item, TxtViewHolder txtViewHolder, String time, String msg) 
        txtViewHolder.getViewReceiver().setVisibility(View.VISIBLE);
        txtViewHolder.getTxtChatRevTime().setText(time);
        txtViewHolder.getTxtChatRevTime().setVisibility(View.VISIBLE);
        txtViewHolder.getTxtChatReceiver().setTextColor(context.getResources()
                .getColor(R.color.color_black));

        boolean oneRowWithLink = false;

        if (forwardUtils.isReceiveForwardUtils(userJID, messageDetail.getCreatedBy(), item.getGroupChatSender() != null && item.getGroupChatSender().length() > 0
                ? item.getGroupChatSender() : item.getChatUser()))
            txtViewHolder.getForwardReceiveLayout().setVisibility(View.VISIBLE);
        else
            txtViewHolder.getForwardReceiveLayout().setVisibility(View.GONE);


        Matcher matcher1 = android.util.Patterns.WEB_URL.matcher(messageDetail.getMessage() != null && (item.getRecall() == null || !item.getRecall()) && messageDetail.getMessage().contains("http") ? messageDetail.getMessage() : "");
        if (matcher1.find()) 
            oneRowWithLink = true;
            String urlMessage = matcher1.group(1);

            LinkPreviewModel linkPreviewModel = linkPreviewModelHashMap.get(urlMessage);
            if (linkPreviewModel != null) 
                //         txtViewHolder.getFullReceiveLayout().setPadding(0,0,0,4);
                txtViewHolder.getLinkRecLayout().setVisibility(View.VISIBLE);
                txtViewHolder.getLinkTitleReceive().setText(linkPreviewModel.getTitle());
                txtViewHolder.getLinkTitleReceive().setTypeface(null, Typeface.BOLD);
                txtViewHolder.getLinkMainUrlReceive().setText(linkPreviewModel.getLinkMainUrl());

                if (linkPreviewModel.getImageUrl() != null && linkPreviewModel.getImageUrl().length() > 0) 
                    linkPreviewModelPositionsMap.put(item.getMid(), linkPreviewModel.getImageUrl());
                    MediaUtils.loadImageWithGlide(context, linkPreviewModel.getImageUrl(),
                            txtViewHolder.getLinkImageUrlReceive(), R.drawable.ic_image_placeholder);
                 else 
                    txtViewHolder.getLinkImageUrlReceive().setVisibility(View.GONE);
                

                if (linkPreviewModel.getDescription() != null && linkPreviewModel.getDescription().length() > 0) 
                    txtViewHolder.getLinkDescriptionReceive().setVisibility(View.VISIBLE);
                    txtViewHolder.getLinkDescriptionReceive().setText(linkPreviewModel.getDescription());
                 else 
                    txtViewHolder.getLinkDescriptionReceive().setVisibility(View.GONE);
                
             else 
                txtViewHolder.getLinkRecLayout().setVisibility(View.GONE);
                parseLink(urlMessage);
            
         else 
            txtViewHolder.getLinkRecLayout().setVisibility(View.GONE);
            //   txtViewHolder.getFullReceiveLayout().setPadding(6,6,6,6);
        

        if (item.getRecall() != null && item.getRecall()) 
            displayRecallInfo(item, txtViewHolder);
         else 
            txtViewHolder.getReceivedRecallImage().setVisibility(View.GONE);
            txtViewHolder.getTxtChatReceiver().setTypeface(Typeface.DEFAULT,
                    Typeface.NORMAL);
            txtViewHolder.getTxtChatReceiver().setTextKeepState(getHtmlChatMessageText
                    (msg));

            Linkify.addLinks(txtViewHolder.getTxtChatReceiver(), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS);
            chatMessageUtils.setRecentChatStatus(txtViewHolder.getImgChatStatus(),
                    item.getStatus());
            new TextReplyViewUtils().showReceiverReplyWindow(txtViewHolder, item, context);
        

        txtViewHolder.getTxtChatReceiver().measure(0, 0);
        if (!oneRowWithLink && txtViewHolder.getTxtChatReceiver().getMeasuredWidth() < (SCREEN_WIDTH * 70) / 100 && txtViewHolder.getTxtChatReceiver().getLineCount() == 1 && TextUtils.isEmpty(item.getReplyTo())) 
            txtViewHolder.getReceiverTimeLayout().measure(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            txtViewHolder.getImgReceivedStar().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

            if (defaultViewRecTimeWidth == -1) 
                defaultViewRecTimeWidth = txtViewHolder.getReceiverTimeLayout().getMeasuredWidth();
            

            //set time layout new parameters
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            params.gravity = Gravity.BOTTOM | Gravity.END;
            params.topMargin = isHighResolutionHeight ? 40 : 25;
            txtViewHolder.getReceiverTimeLayout().setLayoutParams(params);

            //set new width to txt view(because time layout go up..)
            int fixedWidth = (item.getFavourite() != null && item.getFavourite()) ? txtViewHolder.getReceiverTimeLayout().getMeasuredWidth() : defaultViewRecTimeWidth - 10;

            LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(txtViewHolder.getTxtChatReceiver().getMeasuredWidth() + fixedWidth,
                    LinearLayout.LayoutParams.WRAP_CONTENT);
            txtViewHolder.getTxtChatReceiver().setLayoutParams(params1);

            // if one row, set always in left
            txtViewHolder.getTxtChatReceiver().setGravity(Gravity.LEFT);

            //reduce margin bottom to txt view(because space..)
            FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT);
            params2.bottomMargin = isHighResolutionHeight ? -60 : -30;
            txtViewHolder.getViewReceiveLayout().setLayoutParams(params2);

        
        // need this code because it is view holder that reuse layouts
        else 
            //return time layout to basic parameters
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            params.gravity = Gravity.BOTTOM | Gravity.END;
            txtViewHolder.getReceiverTimeLayout().setLayoutParams(params);

            //return chat text view to basic parameters
            LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(TextUtils.isEmpty(item.getReplyTo()) ? LinearLayout.LayoutParams.WRAP_CONTENT :
                    LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            txtViewHolder.getTxtChatReceiver().setLayoutParams(params1);

            // check if is trl language
            if (checkRtl(txtViewHolder.getTxtChatReceiver().getText().toString())) 
                txtViewHolder.getTxtChatReceiver().setGravity(Gravity.RIGHT);
             else 
                txtViewHolder.getTxtChatReceiver().setGravity(Gravity.LEFT);
            

            //return view receive to basic parameters
            FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT);
            txtViewHolder.getViewReceiveLayout().setLayoutParams(params2);
        
    

我发现可能帮助我找到解决方案的线索是以下行 -

Linkify.addLinks(txtViewHolder.getTxtChatReceiver(), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS);

作为接收者,我在这条线上得到了正确的结果,而作为发送者,我得到了错误的结果——这意味着它不能将我的字符串作为 URL。

我在这里缺少什么吗?

【问题讨论】:

【参考方案1】:

已修复 - 我两次致电 getTxtChatReceiver,作为发送方和接收方

【讨论】:

以上是关于Android Linkify.addLinks() 适用于一个 textview 而不是另一个的主要内容,如果未能解决你的问题,请参考以下文章

使用 Linkify.addLinks 与 Html.fromHtml 结合

Android TextView,Linkify 每种语言的美国电话号码

Android Linkify 电话号码 - 如何指定要链接的号码和不链接的号码

使用正则表达式突出显示文本中的链接(Linkify vs Patterns)

android开发要避免的那些坑

我需要从我的 android 应用程序中拨打电话号码吗?从下面哪一个如果有效