I'm setting some attributes with declare-styleable to make a custom view. One of this attributes is a string. What I want to do, is that if I dont set a value in XML for thiks attribute, give it a default value but I don't know how to do it.
<?xml version="1.0" encoding ="utf-8"?>
<resources>
<declare-styleable name ="MyCustomView">
<attr name ="title" format="string"/>
</declare-styleable>
</resources>
In my custom view Im doing this:
private var title = ""
init{
val styledAttr = context.obtainStyledAttributes(attrs,R.styleable.MyCustomView)
title = styledAttr.getString(R.styleable.MyCustomView_title)!! //I cant remove "!!" or I get a type mismatch Required String Found String?
myTextView.text = title
}
In some XML:
<!--Here I can set title attribute but I want that if I dont set it a value, set a default value-->
<com.example.myproject.MyCustomView
android:layout_width="0dp"
android:layout_height = "wrap_content"
/>
CodePudding user response:
//I cant remove "!!" or I get a type mismatch Required String Found String?
title = styledAttr.getString(R.styleable.MyCustomView_title)!!
The type mismatch is because you're doing this:
private var title = ""
You're creating a var
without specifying its type, so the compiler needs to infer it from the value you're assigning. Because you're assigning a String
, it ends up being this:
private var title: String = ""
which is a non-null type - the compiler can't (and shouldn't!) assume you want it to be nullable just by passing a String
, so you have to specify the type explicitly:
private var title: String? = ""
// note the nullable ? ^^^
Now you're still assigning a non-null String
, but you can set title
to null if you want. So you don't need the !!
(which you should avoid using unless you know there's a very good reason to - you're not fixing the problem you've created, just hiding it until it goes wrong)
That's just a general explanation for that error you're getting, so you know what it's about and how to deal with it - the actual solution to your problem is what DarShan posted in the comments:
title = styledAttr.getString(R.styleable.MyCustomView_title) ?: "Default Title"
styledAttr#getString
will return null if the styleable
reference you're looking up doesn't exist on that attr
- which is good, because it means you get a "nothing there" result you can check for. If the result is null, then provide a default fallback value instead
Which is what the elvis operator (?:
) is doing in that line - set title
to the result of getString
, unless that's null, in which case evaluate the stuff after the elvis and use that value instead. So title
either gets assigned a String
from getString
, or "Default Title"
which is also a String
. Either way, it's not going to be null, so title
can stay as the non-null String
type instead of needing to be changed to String?
(never use a nullable type unless you need null values)
You could assign the result of getString
to a temp variable and do title = if (tempString != null) tempString else "DefaultTitle"
but hopefully you can see how Kotlin makes it pretty elegant with its null-handling stuff. That's why nulls show up a lot in Kotlin as a kind of nothing/failure value, so you can easily handle those cases and provide fallbacks