Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android stackoverflow using while loop

I'm using this method to shrink TextView text as it's name suggests:

public static float shrinkTextToFit(String caller, float availableWidth, TextView textView, float startingTextSize, float minimumTextSize) {
    startingTextSize = textView.getTextSize() < startingTextSize ? textView.getTextSize() : startingTextSize;
    Log.i("123", "=========================");
    Log.i("123", caller + " called shrinkTextToFit");
    CharSequence text = textView.getText();
    float textSize = startingTextSize;
    textView.setTextSize(startingTextSize);
    while (!TextUtils.equals(text, (TextUtils.ellipsize(text, textView.getPaint(), availableWidth, TextUtils.TruncateAt.END)))) {
        textSize -= 2;
        Log.i("123", "textSize: " + textSize);
        if ((textSize <= minimumTextSize) || (textSize <= 0)) {
            break;
        } else {
            textView.setTextSize(textSize);
        }
    }
    return textSize;
}

And I'm having a stack-overflow only with this devices (and some times it doesn't happen):

  • Samsung GT-I9192
  • Samsung GT-I9300
  • LG-D290

OS versions: 4.4.2, 4.3

10  at android.widget.TextView.sendAfterTextChanged(TextView.java:8503)
11  at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:10633)
12  at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:970)
13  at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:497)
14  at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:247)
15  at android.text.TextUtils.ellipsize(TextUtils.java:1185)
16  at android.text.TextUtils.ellipsize(TextUtils.java:1079)
17  at android.text.TextUtils.ellipsize(TextUtils.java:1054)
18  at app.utils.Utils.float shrinkTextToFit(float,android.widget.TextView,float,float)

I'm calling this function inside TextWatcher afterTextChanged() and yes that could be the problem, but the idea is to shrink the text size while its being inserted.

@Override
public void afterTextChanged(Editable s) {
    mEditText.removeTextChangedListener(mTextWatcher);
    Utils.shrinkTextToFit("watcher", mAvailableWidth, mEditText, 50, 10);
    mEditText.addTextChangedListener(mTextWatcher);
}

Example Logs:

Start to type letters (scroll to read all the log):

08-01 14:48:50.284    watcher called shrinkTextToFit
08-01 14:48:50.676    =========================
08-01 14:48:50.677    watcher called shrinkTextToFit
08-01 14:48:51.749    =========================
08-01 14:48:51.749    watcher called shrinkTextToFit
08-01 14:48:51.749    textSize: 48.0
08-01 14:48:51.750    textSize: 46.0
08-01 14:48:51.751    textSize: 44.0
08-01 14:48:51.752    textSize: 42.0
08-01 14:48:52.500    =========================
08-01 14:48:52.501    watcher called shrinkTextToFit
08-01 14:48:52.501    textSize: 48.0
08-01 14:48:52.501    textSize: 46.0
08-01 14:48:52.501    textSize: 44.0
08-01 14:48:52.501    textSize: 42.0
08-01 14:48:52.501    textSize: 40.0
08-01 14:48:52.503    textSize: 38.0
08-01 14:48:52.504    textSize: 36.0
08-01 14:48:53.013    =========================
08-01 14:48:53.013    watcher called shrinkTextToFit
08-01 14:48:53.013    textSize: 48.0
08-01 14:48:53.013    textSize: 46.0
08-01 14:48:53.013    textSize: 44.0
08-01 14:48:53.014    textSize: 42.0
08-01 14:48:53.015    textSize: 40.0
08-01 14:48:53.015    textSize: 38.0
08-01 14:48:53.015    textSize: 36.0
08-01 14:48:53.016    textSize: 34.0
08-01 14:48:53.017    textSize: 32.0
08-01 14:48:53.020    textSize: 30.0
08-01 14:48:59.948    =========================
08-01 14:48:59.949    watcher called shrinkTextToFit
08-01 14:48:59.949    textSize: 48.0
08-01 14:48:59.949    textSize: 46.0
08-01 14:48:59.949    textSize: 44.0
08-01 14:48:59.949    textSize: 42.0
08-01 14:48:59.950    textSize: 40.0
08-01 14:48:59.950    textSize: 38.0
08-01 14:48:59.950    textSize: 36.0
08-01 14:48:59.950    textSize: 34.0
08-01 14:48:59.951    textSize: 32.0
08-01 14:48:59.951    textSize: 30.0
08-01 14:48:59.951    textSize: 28.0

Start to erase letters:

08-01 14:48:59.953    =========================
08-01 14:48:59.953    watcher called shrinkTextToFit
08-01 14:48:59.954    textSize: 48.0
08-01 14:48:59.954    textSize: 46.0
08-01 14:48:59.954    textSize: 44.0
08-01 14:48:59.954    textSize: 42.0
08-01 14:48:59.954    textSize: 40.0
08-01 14:48:59.954    textSize: 38.0
08-01 14:48:59.954    textSize: 36.0
08-01 14:48:59.954    textSize: 34.0
08-01 14:48:59.954    textSize: 32.0
08-01 14:48:59.954    textSize: 30.0
08-01 14:49:00.116    =========================
08-01 14:49:00.116    watcher called shrinkTextToFit
08-01 14:49:00.116    textSize: 48.0
08-01 14:49:00.117    textSize: 46.0
08-01 14:49:00.117    textSize: 44.0
08-01 14:49:00.117    textSize: 42.0
08-01 14:49:00.117    textSize: 40.0
08-01 14:49:00.117    textSize: 38.0
08-01 14:49:00.117    textSize: 36.0
08-01 14:49:00.121    =========================
08-01 14:49:00.121    watcher called shrinkTextToFit
08-01 14:49:00.121    textSize: 48.0
08-01 14:49:00.121    textSize: 46.0
08-01 14:49:00.121    textSize: 44.0
08-01 14:49:00.121    textSize: 42.0
08-01 14:49:00.284    =========================
08-01 14:49:00.284    watcher called shrinkTextToFit
08-01 14:49:00.288    =========================
08-01 14:49:00.288    watcher called shrinkTextToFit
08-01 14:49:00.444    =========================

What am I doing wrong and how can I improve this solution to prevent this exceptions?

like image 406
GuilhE Avatar asked Jul 31 '15 10:07

GuilhE


2 Answers

I think you should do the math for textsize, and run your setTextSize one time.

Even if you use some kind of temporary view to do the work against, get the size from that. Instead of calling against the view with the eventlistener on it.

like image 54
Justin Mecham Avatar answered Nov 11 '22 13:11

Justin Mecham


I've found the solution, or so it seams, and it's quite odd and strange. So I've noticed something weird wile I was debugging (because for the first time I could reproduce this error):

I've noticed when the text was "green" the text was being "well parsed":

enter image description here enter image description here

but some times the text wasn't "green", specially if the text was somenthing like "... / ...":

enter image description here enter image description here


And that was causing the StackOverflow because TextUtils.ellipsize wasn't returning and the debugger was acting a bit strange too.

Changing this:

CharSequence text = textView.getText();

To this:

CharSequence text = textView.getText().toString();

Is the solution.
And now it's working. Thanks IntelliJ for being the best IDE ever :)

like image 31
GuilhE Avatar answered Nov 11 '22 11:11

GuilhE