zoukankan      html  css  js  c++  java
  • TextView展示富文本时emoj或图片和文字不对齐的解决方案

    在项目中,回复框、聊天界面的显示往往会有emoj或者图片,但是一个比较头疼的问题是,会出现emoj表情或者图片和文字的位置不对齐,总是有偏移,这样很影响用户体验的。下面会总结一下如何解决这个问题。

    本文所列举的解决方案是参考一个非常给力的表情键盘项目:https://github.com/w446108264/XhsEmoticonsKeyboard

    另外一个非常给力的是google提供的开源demo:https://github.com/googlesamples/android-EmojiCompat,文档地址为:https://developer.android.com/guide/topics/ui/look-and-feel/emoji-compat.html#using-emojicompat-for-imes

    1. TextView设置

    /**
         * 解析评论内容,包含富文本表情
         *
         * @param textView
         * @param text
         */
        private void setRichText(TextView textView, String text) {
            // 将文本转换为span
            Spanned span = Html.fromHtml(text);
            int fontSize = UIHelper.getFontHeight(textView);
            if (TextUtils.isEmpty(text)) {
                textView.setVisibility(View.GONE);
            } else {
                textView.setFocusable(false);
                textView.setLongClickable(false);
                span = InputHelper.displayEmoji(context.getResources(), span, fontSize, Math.round(TDevice.dp2px(5.0f/2.0f)) );
    //            去除下划线
                SpannableString spannableString = new SpannableString(span);
                spannableString.setSpan(new NoUnderlineSpan(),0,span.length(),Spanned.SPAN_MARK_MARK);
                textView.setText(spannableString);
            }
        }

    2. 展示文字和表情

    /**
         * 展示文字和表情
         * @param res
         * @param s
         * @param fontSize 字体大小
         * @param lineSpace 行间距
         * @return
         */
        public static Spannable displayEmoji(Resources res, CharSequence s, int fontSize, int lineSpace) {
            String str = s.toString();
            Spannable spannable;
            if (s instanceof Spannable) {
                spannable = (Spannable) s;
            } else {
                // 构建文字span
                spannable = new SpannableString(str);
            }
            for (int i = 0; i < str.length(); i++) {
                int index1 = str.indexOf("[", i);
                int length1 = str.indexOf("]", index1 + 1);
                int index2 = str.indexOf(":", i);
                try {
                    String emojiStr = str.substring(index1, length1 + "]".length());
                    int resId = getEmojiResId(emojiStr);
                    if (resId > 0) {
                        // 构建图片span
                        Drawable drawable = res.getDrawable(resId);
                        if (drawable != null) {
                            int itemHeight;
                            int itemWidth;
                            if (fontSize == WRAP_DRAWABLE) {
                                itemHeight = drawable.getIntrinsicHeight();
                                itemWidth = drawable.getIntrinsicWidth();
                            } else {
                                itemHeight = fontSize;
                                itemWidth = fontSize;
                            }
                            drawable.setBounds(0, 0, itemHeight, itemWidth);
                            // 自定义ImageSpan,实现文字和表情的对齐
                            EmojiSpan imageSpan = new EmojiSpan(drawable,lineSpace);
                            spannable.setSpan(imageSpan, index1, length1 + "]".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                        }
                    }
                } catch (Exception e) {
                }
            }
            return spannable;
        }

    3.处理表情图片的工具类,主要是计算表情的显示大小和位置

    public class EmojiSpan extends ImageSpan {
        private int lineSpace;
        public EmojiSpan(Drawable drawable,int lineSpace) {
            super(drawable);
            this.lineSpace = lineSpace;
        }
        public EmojiSpan(Context context, int resourceId) {
            super(context, resourceId);
        }
        @Override
        public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fontMetricsInt) {
            Drawable drawable = this.getDrawable();
            Rect rect = drawable.getBounds();
            if(fontMetricsInt != null) {
                Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
                int fontHeight = fmPaint.bottom - fmPaint.top;
                int drHeight = rect.bottom - rect.top;
                int top = drHeight / 2 - fontHeight / 4;
                int bottom = drHeight / 2 + fontHeight / 4;
                fontMetricsInt.ascent = -bottom;
                fontMetricsInt.top = -bottom;
                fontMetricsInt.bottom = top;
                fontMetricsInt.descent = top;
            }
            return rect.right;
        }
        @Override
        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
            Drawable drawable = this.getDrawable();
            canvas.save();
            int transY = (bottom - top - drawable.getBounds().bottom) / 2 + top - lineSpace;
            canvas.translate(x, (float)transY);
            drawable.draw(canvas);
            canvas.restore();
        }
    }

    4.获取TextView字体大小的工具

    /**
         * 获取TextView的字体大小
         * @param textView
         * @return
         */
        public static int getFontHeight(TextView textView) {
            Paint paint = new Paint();
            paint.setTextSize(textView.getTextSize());
            Paint.FontMetrics fm = paint.getFontMetrics();
            return (int) Math.ceil(fm.bottom - fm.top);
        }
  • 相关阅读:
    【做题】提高组过关测试题1
    【做题】arc078_f-Mole and Abandoned Mine——状压dp
    【学习】Hall’s Marriage Theorem
    【做题】arc072_f-Dam——维护下凸包
    一文尽览近似最近邻搜索中的哈希与量化方法
    InsightFace源码以及pre-train模型以及使用
    无法解析的外部符号 jpeg_std_error
    威布尔weibull distribution
    中科院- 生物特征识别概述
    Face-Resources
  • 原文地址:https://www.cnblogs.com/renhui/p/8629616.html
Copyright © 2011-2022 走看看