自定义布局实现TextView控制行数显示并显示全部按钮

一、先看一下要实现的效果图
自定义布局实现TextView控制行数显示并显示全部按钮
此处的实现与可展示的TextView实现不一样,这里的业务场景是点击“查看全部”后,跳转到其它界面展示全部内容,而不是在当前界面,所以此处的"查看全部"只是用于点击事件的安置功能。
当文本长度,在三行内能够完全展示出来,则隐藏“查看全部”。
二、实现解析
此处的功能点,是在怎么让文本只显示两行多一点,而不直接把三行充满,然后再显示三个点。其实Paint类里面,内置了计算文字显示长度的方法。我们只需要调用这个方法得到文本展示的总长度、然后再与控件长度、以及展示行数固定值,进行计算即可。直接看代码吧。
三、关键代码

package com.migu.recyclerviewtest;

import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class CustomContentShowTextView extends RelativeLayout {
    private TextView mContentTextView;
    private LinearLayout mAllContentLLT;

    public CustomContentShowTextView(Context context) {
        super(context);
        init(context);
    }

    public CustomContentShowTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CustomContentShowTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.custom_textview_description, this);
        mContentTextView = view.findViewById(R.id.description);
        mAllContentLLT = view.findViewById(R.id.all_content_llt);
    }

    public void setText(String text) {
        String content = getSubString(mContentTextView, text);
        if (content != null) {
            mContentTextView.setText(content);
        }
    }

    private String getSubString(TextView tv, String content){
        float width = tv.getPaint().measureText(content);
        //这里只是为了方便,用屏幕宽度代替了textview控件宽度,如果需要精准控制,可以换成控件宽度
        //这里测试时是将textview全屏的,如果有左右margin则从这里减去就行
        float tvWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
        //计算文字的长度,相对于控件长度而言,能显示多少行
        float lines = width / tvWidth;
        //这个>3是判断是否文字展示的行数超过3行了
        if(lines > 3){
            mAllContentLLT.setVisibility(VISIBLE);
            //这里直接用长度/行数=每行显示多少个字,*2.7代表需要截取2.7行的字数
            int index = (int)((content.length()/lines) * (2.7));
            return content.substring(0, index) + "...";
        } else {
            mAllContentLLT.setVisibility(GONE);
        }
        return content;
    }

    public void setOnMoreClickListener(OnClickListener clickListener) {
        mAllContentLLT.setOnClickListener(clickListener);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="3"
        android:ellipsize="end"
        android:text="12121321321321312311212132132132131231121213213213213123112121321321321312311212132132132131231121213213213213123112121321321321312311212132132132131231"
        android:textSize="14dp" />

    <LinearLayout
        android:id="@+id/all_content_llt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/description"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="查看全部"
            android:textColor="@android:color/holo_red_light"
            android:textSize="14dp" />

        <ImageView
            android:layout_width="6dp"
            android:layout_height="10dp"
            android:src="@mipmap/right_arrow"
            android:layout_marginLeft="4dp" />
    </LinearLayout>

</RelativeLayout>


//使用就很简单了,直接设置内容即可,至于OnclickListener,根据业务需要设置即可。
CustomContentShowTextView testTextview = findViewById(R.id.testTextview);
        testTextview.setText("不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?" +
                "不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?" +
                "不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?不足三行代码的情况下,会怎么展示呢?");

四、加强版
上面的getSubString方法当中使用到的裁剪字符串,不够精确,毕竟是使用字符串的整体平均数来计算前三行的字数,这导致精确度很差。所以使用下面的加强版方法,可以大大减少差距。

private String getSubString(TextView tv, String content){
        float width = tv.getPaint().measureText(content);
        //这里只是为了方便,用屏幕宽度代替了textview控件宽度,如果需要精准控制,可以换成控件宽度
        //这里测试时是将textview全屏的,如果有左右margin则从这里减去就行
        float tvWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
        //计算文字的长度,相对于控件长度而言,能显示多少行
        float lines = width / tvWidth;
        //这个>3是判断是否文字展示的行数超过3行了
        if(lines > 3){
            mAllContentLLT.setVisibility(VISIBLE);
            //这里计算展示三行需要的字数
            int index = (int)((content.length()/lines) * 3);
            //使用控件的宽度来限制位置
            float subTvWidth = (float) (tvWidth * 2.75);
            String subString = "";
            for (int i = index; i >= 0; i--) {
                subString = content.substring(0, i) + "...";
                float subWidth = tv.getPaint().measureText(subString);
                if (subWidth <= subTvWidth) {
                    break;
                }
            }
            //毕竟是展示内容,如果只有两三个字,肯定是不对的
            if (!TextUtils.isEmpty(subString) && subString.length() > 3) {
                return subString;
            } else {
                return content.substring(0, (int)((content.length()/lines) * (2.7))) + "...";
            }
        } else {
            mAllContentLLT.setVisibility(GONE);
        }
        return content;
    }

作者:沧水巫云
博客:http://blog.csdn.NET/amir_zt/
以上原创,转载请注明出处,谢谢。
https://blog.csdn.net/amir_zt/article/details/113343428

上一篇:安卓textview的DrawableTop属性图片加间距


下一篇:android动态改变TextView字体大小遇到的问题