How do android get that maximum display of textview

  • 2021-12-13 09:16:26
  • OfStack

Method 1

One method used in the work, although not particularly accurate, but the effect is still good, share it here.


    /**
     *  Get textview A maximum of several words can be displayed 
     * @param text  Text content 
     * @param size  Text font size 
     * @param maxWidth textview Maximum width of 
     * @return
     */
    private float getLineMaxNumber(String text, float size,float maxWidth) {
        if (null == text || "".equals(text)){
            return 0;
        }
        Paint paint = new Paint();
        paint.setTextSize(size);
        // Get the total length of the text content 
        float textWidth = paint.measureText(text);
        // textWidth
        float width = textWidth / text.length();
        float total = maxWidth / width;
        return total;
    }

The above method is not very precise, but it is suitable for RecyclerView or ListView to avoid generating too many objects

Method 2


/**
     *  Get textview1 A line can display a maximum of several words ( Need to be in TextView After the measurement is completed, )
     *
     * @param text      Text content 
     * @param paint    textview.getPaint()
     * @param maxWidth textview.getMaxWidth()/ Or the specified value , Such as 200dp
     */
    private int getLineMaxNumber(String text, TextPaint paint, int maxWidth) {
        if (null == text || "".equals(text)) {
            return 0;
        }
        StaticLayout staticLayout = new StaticLayout(text, paint, maxWidth, Layout.Alignment.ALIGN_NORMAL
                , 1.0f, 0, false);
        // Get the 1 Character subscript displayed at the end of the line 
        return staticLayout.getLineEnd(0);
    }

Using StaticLayout, you can easily get the maximum number of characters that can be displayed in one line

Extension:
For a single line TextView, when the string exceeds 1 line, how do you get the part of the string that is not displayed?
After textview sets the maximum number of lines to 1, the text exceeds textview, and the ellipsis is displayed at the end of textView, so I want to know what the ellipsis represents
Thoughts:
Assuming that the width of TextView is a specific value set in xml, such as 300dp,
(To simplify this problem, if it is set to match_parent or wrap_content, the width of the program needs to be calculated at runtime, while direct getWidth always returns 0, which is troublesome.)
For example, it is configured like this:


  <TextView
        android:id="@+id/textView"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:singleLine="true" />

Then fill in an overly long string, such as this:


String str = "If you really want to hear about it, the first thing you'll probably want to know";
 This will lead to incomplete display, like this: 
If you really want to hear about it, the first thin...

 So, if you want to get the number of characters that have been displayed, or the number of characters that have not been displayed, the key is how to calculate each 1 The width of three characters. 
 Then traverse the string, and the current n The sum of the widths of characters, exceeding TextView Width, the number of characters displayed is obtained. 

String str = "If you really want to hear about it, the first thing you'll probably want to know";
mTextView = (TextView) findViewById(R.id.textView);

//  Calculation TextView Width: xml Width defined in 300dp , converted to px
float textViewWidth = convertDpToPixel(300);
float dotWidth = getCharWidth(mTextView, '.');
Log.d(TAG, "TextView width " + textViewWidth);

int sumWidth = 0;
for (int index=0; index<str.length(); index++) {
    //  Calculate every 1 Width of three characters 
    char c = str.charAt(index);
    float charWidth = getCharWidth(mTextView, c);
    sumWidth += charWidth;
    Log.d(TAG, "#" + index + ": " + c + ", width=" + charWidth + ", sum=" + sumWidth);
    
    if (sumWidth + dotWidth*3 >= textViewWidth) {
        Log.d(TAG, "TextView shows #" + index + " char: " + str.substring(0, index));
        break;
    }
}

// Dp Turn Px
private float convertDpToPixel(float dp){
    Resources resources = getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return px;
}

//  Calculate every 1 Width of three characters 
public float getCharWidth(TextView textView, char c) {
    textView.setText(String.valueOf(c));
    textView.measure(0, 0);
    return textView.getMeasuredWidth();
} 

The results are as follows: the test passed on Glory 3C and LG G3 (G3 shows one more character than the calculated result):

10-22 01:17:42.046: D/Text(21495): TextView width 600.0
10-22 01:17:42.048: D/Text(21495): #0: I, width=8.0, sum=8
10-22 01:17:42.049: D/Text(21495): #1: f, width=9.0, sum=17
10-22 01:17:42.049: D/Text(21495): #2: , width=7.0, sum=24
10-22 01:17:42.049: D/Text(21495): #3: y, width=14.0, sum=38
......
10-22 01:17:42.053: D/Text(21495): #17: t, width=9.0, sum=213
10-22 01:17:42.053: D/Text(21495): #18: , width=7.0, sum=220
10-22 01:17:42.053: D/Text(21495): #19: t, width=9.0, sum=229
......

10-22 01:17:42.061: D/Text(21495): #50: n, width=16.0, sum=575
10-22 01:17:42.061: D/Text(21495): #51: g, width=16.0, sum=591
10-22 01:17:42.061: D/Text(21495): TextView shows #51 char: If you really want to hear about it, the first thin


Related articles: