Android TextView多行展示文本,多余"..."省略,文末用".pdf"格式结尾

如题需求:UED图如下,


image.png

如图,也就是文末用....pdf结尾。

碰到的主要问题:如何在recycleview中动态计算 textview的宽高。考虑到recycleview 复用机制无法拿到TextView的宽高,使用自定义TextView来获取宽高。
具体看代码:

public class MyEllipsisTextView extends AppCompatTextView {

    private static final String TAG = MyEllipsisTextView.class.getSimpleName();
    private String mText;
    private int mTextColor;
    private float mTextSize;


    private Paint mPaint;
    private Rect mBound;
    private int mWidth;


    public MyEllipsisTextView(Context context) {
        this(context, null);
    }

    public MyEllipsisTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyEllipsisTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyEllipsisTextView, defStyleAttr, 0);
        mText = a.getString(R.styleable.MyEllipsisTextView_mText);
        mTextSize = a.getDimension(R.styleable.MyEllipsisTextView_mTextSize, 15f);
        mTextColor = a.getColor(R.styleable.MyEllipsisTextView_mTextColor, Color.YELLOW);
        a.recycle();
        init();
    }

    private void init() {

        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
        mPaint.setColor(mTextColor);
        mBound = new Rect();

        mPaint.getTextBounds(mText, 0, mText.length(), mBound);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //1. 获取 自定义 View 的宽度,高度 的模式
        int heigthMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int height = MeasureSpec.getSize(heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        mWidth = width;

        if (MeasureSpec.AT_MOST == heigthMode) {
            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            height = bounds.height() + getPaddingBottom() + getPaddingTop();
        }

        if (MeasureSpec.AT_MOST == widthMode) {
            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            width = bounds.width() + getPaddingLeft() + getPaddingRight();
        }
        setMeasuredDimension(width, height);
        setMyText();
    }

    private void setMyText() {
        setTextColor(mTextColor);
        setTextSize(mTextSize);
        setWidth(mWidth);
        setHeight(Utils.getFontHeight(mTextSize) * 2);
        setText(Utils.ellipsizeString(this, mText, mWidth));
    }

    public void setInitText(String charSequence) {
        mText = charSequence;
    }


//    @Override
//    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
//        canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
//        Log.d(TAG, "setText:  canvas:" + canvas.toString());
//    }


//    @Override
//    public void setText(CharSequence text, BufferType type) {
//        super.setText(text, type);
//        Log.d(TAG, "setText:  text:" + text + ",type:" + type);
////        setText(mText);
////        setTextColor(mTextColor);
////        setTextSize(mTextSize);
//        setWidth(mWidth);
//    }
}
 <declare-styleable name="MyEllipsisTextView">
        <attr name="mTextSize" format="dimension" />
        <attr name="mTextColor" format="color" />
        <attr name="mText" format="string" />
    </declare-styleable>
    /**
     * 字符串显示到textView, textView maxLines=2
     * 如果字符串太长显示不下,则用省略号代替
     * 省略号的位置在第一行末尾
     *
     * @param textView 显示字符串的view
     * @param str      要显示的字符串
     * @param width    显示字符串的view的宽
     * @return 处理后带省略号的字符串
     */
    public static String ellipsizeString(TextView textView, String str, int width) {
        if (TextUtils.isEmpty(str)) return str;
        Paint paint = textView.getPaint();
        //文字总宽小于2倍的view宽,说明小于2行,直接返回
        if (paint.measureText(str) < 2 * width) {
            return str;
        }

        //存储显示到view的每行文字
        List<String> list = new ArrayList<>();

        int len = 0;
        int start, end = 0;

        while (len < str.length()) {
            len += end;
            int count = paint.breakText(str, end, str.length(), true, width, null);
            start = end;
            end = end + count;
            list.add(str.substring(start, end));
        }

        String line1 = list.get(0);
        String line2 = list.get(1);
        int line2Width = (int) paint.measureText(line2);
        String[] split1 = str.split("\\.");
        if (split1.length < 2) return str;
        String mString = "...." + split1[1];
        int subWidth = (int) paint.measureText(mString);
        int widthTemp = line2Width;
        while (widthTemp + subWidth > line2Width) {
            if (line2.length()<1) break;
            line2 = line2.substring(0, line2.length() - 1);
            widthTemp = (int) paint.measureText(line2);
        }
        return line1 + line2 + mString;
    }

    public static int getFontHeight(float fontSize)
    {
        Paint paint = new Paint();
        paint.setTextSize(fontSize);
        Paint.FontMetrics fm = paint.getFontMetrics();
        return (int) Math.ceil(fm.descent - fm.top) + 2;
    }

使用

txt = "看了就变聪明怎么都漂亮的不灵不灵的文档收到货水电费可接受的山东矿机看了就变聪明怎么都漂亮的不灵不灵的文档收到货水电费可接受的山东矿机.pdf";

myText.setInitText(txt);
S90715-152327.jpg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • 感觉自己很久很久没有写东西了,突然听到请回答,1988的歌,然后就怀念起了大学的日子。我想,应该很多人会在,夜...
    你会愿意听我的故事吧阅读 219评论 0 0
  • 翻译插件https://github.com/YiiGuxing/TranslationPlugin#action...
    毕加森阅读 249评论 0 0
  • vuex是vue的一个数据状态管理工具,简单的来说他就是一个vue的仓库用来存储vue的数据方便组件之间的调用。 ...
    hudaren阅读 1,150评论 0 2
  • どうして夜のあいだ国旗が降ろされてしまうのか、僕にはその理由がわからなかった。夜のあいだだってちゃんと国家は存続し...
    魚子醬阅读 146评论 0 0
  • 昨天去办了小油的医保卡,还有自己的失业生育补助 没有多少钱… 技能等级补贴没有 下个月宝宝的保险7000多,爸爸的...
    云云蔡阅读 53评论 0 1