1

I am using a TextEdit that only accepts numbers as input type and I would like to set the value of the TextEdit when a button is pressed. However, I can't get this to work.

When I just do textWithAmount.setText(balance), with balance being a long, I get a squiggly line saying that this doesn't conform the setText function and I can't run my code.

When I cast it to Int (setText(balance.toInt()), I get the following error:

android.content.res.Resources$NotFoundException: String resource ID #0x2710

When I cast it to String (setText(balance.toString()), I get the following error:

java.lang.ClassCastException: android.text.SpannableStringBuilder cannot be cast to java.lang.Long

Kotlin Code:

val buttonAll = findViewById<Button>(R.id.buttonWithAll)
var balance : Long = 0
buttonAll.setOnClickListener{
                textAmount.setText(balance.toInt())
            }

XML:

<EditText
        android:id="@+id/textWithAmount"
        android:layout_width="228dp"
        android:layout_height="68dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="10dp"
        android:ems="100"
        android:importantForAutofill="no"
        android:inputType="number"
        app:layout_constraintEnd_toStartOf="@+id/buttonWithAll"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView4" />

    <Button
        android:id="@+id/buttonWithAll"
        android:layout_width="68dp"
        android:layout_height="68dp"
        android:layout_marginEnd="9dp"
        android:text="@string/all"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textWithAmount"
        app:layout_constraintTop_toTopOf="@+id/textWithAmount" />

Does anyone know a solution to this? Any answers would be appreciated

Edit: I just realized I also have a textChangedListener on the same TextEdit which is probably called when I fill it. Maybe something is wrong there:

textAmount.addTextChangedListener { text ->
                    val input : Long = text as Long
                    if(input > cash){
                        textAmount.setText(cash.toString())
                    }
                }```
4
  • are you using Spannable in any sort? Commented May 10, 2021 at 13:38
  • @cutiko No, I'm not Commented May 10, 2021 at 13:40
  • balance.toString() doesn't cast to a String. It creates a new String object by converting the input Long. We'll have to see more of your code about this to know what went wrong. What you posted should just be passing a String to setText so that should work fine. Your error says you're trying to cast SpannableStringBuilder to a Long, which is something you must be doing elsewhere in your code. Please show the code where you have put something like as Long Commented May 10, 2021 at 13:42
  • @Tenfour04 I just noticed what might be the problem; I also have a textchangedlistener on the same texfield and it is probably called when i programmatically fill the textedit. The code of it is here: textAmount.addTextChangedListener { text -> val input : Long = text as Long if(input > cash){ textAmount.setText(cash.toString()) } } Commented May 10, 2021 at 13:48

2 Answers 2

2

setText(balance.toString()) is correct. Your error is in the code you posted in your comment.

The java.lang.ClassCastException is because you are casting something that is not a Long to a Long. I think maybe you need clarification on the difference between converting something and casting something. Casting (using the as keyword) does not convert one type of object into another. Casting is you telling the compiler that the object already is that other type of object.

When you cast, the compiler takes your word for it that you know better than the compiler, and it allows you to treat it like that other type of object. Then at runtime, if your declaration to the compiler was incorrect, it will crash with a ClassCastException.

For those reasons, you should rarely be using as at all. It is for special cases, like if you had a List<Any> and you want to pull something out of it and treat it as a more specific class. Or when you are writing a class that works with generics and run into a situation where the compiler cannot figure out a type. Or when the object implements multiple interfaces and there is ambiguity about which function overload you want to pass it to.

When you get text from a TextView, it is some kind of CharSequence object, specifically a SpannableStringBuilder. If you want to use it as a Long, you must convert to a Long, not cast to a Long. You should also account for the fact that the existing content passed to your listener may not be a non-null text that can truly be converted to a Long. For that, you can do something like using the Elvis operator to set a default value if the text cannot be converted.

textAmount.addTextChangedListener { text ->
    val input : Long = text?.toString()?.toLongOrNull() ?: 0L
    if(input > cash){                         
        textAmount.setText(cash.toString())
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer and the explanation, it works now!
text is nullable and you are handling empty text neither, which would throw exception @Tenfour04
True, there are further issues to work out. I'll update.
2

What is happening is that balance.toInt() is a number so when you use setText you are using the method that takes a number argument.

setText(@Stringres ...)

Since that is just a number and not a string resource generated in the strings.xml file it can't find it and it crashes

Try with this

setText("$balance")

Regarding the text listener part there could be some improvements as well

val input = editable?.toString()?.toLongOrNull() ?: return@addTextChangedListener

The lambda argument there is nullable editable, not text, and when parsing text to what ever number type there is always number format exception chance, by example, empty text.

1 Comment

Just an FYI, I think toLongOrNull() is considered more proper than catching NumberFormatException, based on this. "As a rule of thumb, you should not be catching exceptions in general Kotlin code. That’s a code smell."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.