android – Get current visible text in textview-ThrowExceptions

Exception or error:

I have a long passage in a TextView which is wrapped around by ScrollView. Is there any way to find the current visible text?

I can find the number of lines, line height in textview and also scrollx and scrolly from scrollview, but find the linkage to the current displayed text. Please help! Thanks.

How to solve:

It is simple to do this:

int start = textView.getLayout().getLineStart(0);
int end = textView.getLayout().getLineEnd(textView.getLineCount() - 1);

String displayed = textView.getText().toString().substring(start, end);

###

Here. Get the line number of the first displayed line. Then get the line number of the second displayed line. Then get the text and count the number of words.

private int getNumberOfWordsDisplayed() {
        int start = textView.getLayout().getLineStart(getFirstLineIndex());
        int end = textView.getLayout().getLineEnd(getLastLineIndex());
        return textView.getText().toString().substring(start, end).split(" ").length;
    }

    /**
     * Gets the first line that is visible on the screen.
     *
     * @return
     */
    public int getFirstLineIndex() {
        int scrollY = scrollView.getScrollY();
        Layout layout = textView.getLayout();
        if (layout != null) {
            return layout.getLineForVertical(scrollY);
        }
        Log.d(TAG, "Layout is null: ");
        return -1;
    }

    /**
     * Gets the last visible line number on the screen.
     * @return last line that is visible on the screen.
     */
    public int getLastLineIndex() {
        int height = scrollView.getHeight();
        int scrollY = scrollView.getScrollY();
        Layout layout = textView.getLayout();
        if (layout != null) {
            return layout.getLineForVertical(scrollY + height);
        }
        return -1;
    }

###

Using textView.getLayout().getEllipsisStart(0) only works if android:singleLine=”true”

Here is a solution that will work if android:maxLines is set:

public static String getVisibleText(TextView textView) {
    // test that we have a textview and it has text
    if (textView==null || TextUtils.isEmpty(textView.getText())) return null;
    Layout l = textView.getLayout();
    if (l!=null) {
        // find the last visible position
        int end = l.getLineEnd(textView.getMaxLines()-1);
        // get only the text after that position
        return textView.getText().toString().substring(0,end);
    }

    return null;
}

Remember: this works after the view is already loaded.

Usage:

textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            Log.i("test" ,"VisibleText="+getVisibleText(textView));
        }
    });

###

You claim that you know scrollY, the current number of pixels scrolled. You also know the height of the window you’re considering in pixels, so call that scrollViewHeight. Then

int scrollY; // This is your current scroll position in pixels.
int scrollViewHeight; // This is the height of your scrolling window.
TextView textView; // This is the TextView we're considering.

String text = (String) textView.getText();
int charsPerLine = text.length() / textView.getLineCount();
int lineHeight = textView.getLineHeight();

int startLine = scrollY / lineHeight;
int endLine = startLine + scrollViewHeight/lineHeight + 1;

int startChar = charsPerLine * startLine;
int endChar = charsPerLine * (endLine+1) + 1;
String approxVisibleString = text.substring(startChar, endChar);

It’s an approximation, so use it as a last resort.

###

I also having about the same problem myself. I needed first visible line from textview currently visible in recyclerview. If you are trying to get currently displayed first line of textview in recyclerview you may use the following code:

  TextView tv = (TextView) recyclerView.getChildAt(0); //gets current visible child view
  // this is for top visible 
  //view or the textview directly
   Rect r1 = new Rect();
   tv.getHitRect(r1);//gets visible rect of textview
   Layout l = tv.getLayout();

   int line = l.getLineForVertical(-1 * r1.top);//first visible line
   int start = l.getLineStart(line);//visible line start
   int end = l.getLineEnd(line);//visible line end

   String displayed = tv.getText().toString().substring(start, end);

###

try use getEllipsisStart()

int end = textView.getLayout().getEllipsisStart(0);

###

This depends on the use of Ellipsize in the TextView. Try this:

public String getVisibleText(TextView tv) {
    int lastLine = tv.getMaxLines() < 1 || tv.getMaxLines() > tv.getLineCount() ? tv.getLineCount() : tv.getMaxLines();
    if (tv.getEllipsize() != null && tv.getEllipsize().equals(TextUtils.TruncateAt.END)) {
        int ellCount = tv.getLayout().getEllipsisCount(lastLine - 1);
        if (ellCount > 0 && tv.length() > ellCount)
            return tv.getText().toString().substring(0, tv_title.getText().length() - ellCount);
        return tv.getText().toString();
    } else {
        int end = tv.getLayout().getLineEnd(lastLine - 1);
        return tv.getText().toString().substring(0, end);
    }
}

textView.post(new Runnable() {
    @Override
    public void run() {
        Log.d(TAG, getVisibleText(textView));
    }
});

Leave a Reply

Your email address will not be published. Required fields are marked *