It is typical to set the inputType=textPassword for fields where users would type in anything that is at risk, like...a password. And when the user types it, each character they type is briefly flashed to let the user know what was actually entered and then turns into an asterisk so that casual observers (spies) have a lot more difficulty seeing what is typed.
Generally this works fine.
I have a specific case where for security reasons the character must NOT be flashed. Instead I want to simply display the asterisk.
I could handle each tap individually via setOnKeyListener(), but it seems like this should be easy. However I don't see any built-in solution. Please tell me that I'm missing something.
Thanks for all those who commented, prodded, and pointed out excellent tips. Using these valuable assists I was able to do something that was actually pretty easy and seems to work perfectly for this situation.
The trick is to override PasswordTransformationMethod and force your EditText to use this new one. The original charAt() method uses Spannable that waits a second and half before hiding it. By overriding that method your code can do something much simpler.
Here's an example of the custom class (in kotlin)
class ReallyHideMyPassword : PasswordTransformationMethod() {
companion object {
const val HIDE_CHAR = '*'
}
override fun getTransformation(source: CharSequence, view: View): CharSequence {
return PasswordCharSequence(source)
}
inner class PasswordCharSequence (private val source: CharSequence) : CharSequence {
override val length: Int
get() = source.length
override fun get(index: Int): Char = HIDE_CHAR
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
return source.subSequence(startIndex, endIndex)
}
}
}
And to use this in your EditText:
val et = findViewById<EditText>(R.id.my_password_edittext)
et.transformationMethod = ReallyHideMyPassword();
Turns out that this is similar to https://stackoverflow.com/a/23110194/624814 (thanks Per.J!), but now you have it in kotlin. It's so similar that this question will probably be closed as too similar. But the wording of the question should help people find the answer more easily than the other post.
You are not missing anything, I've struggled with this in the past and until now I've found no built-in solution, I've used addTextChangedListener to do this and external libraries.
Disabling this setting does exactly what you asked, and it applies to every app but I guess you only can change this by code on a rooted phone.
I know this is no solution but it's a statement that this isn't available for developers and we have to make our own thing.
EDIT:
The comments offers great solutions but as you said, not built-in.
Related
This might be a very silly question, but I am logging the methods that are triggered in my app as strings. When an issue is submitted, I would like to automatically input the text of the strings as parameters for methods. E.g:
For method:
fun assignPot(potType: PotType, ball: DomainBall, action: PotAction) {...}
I'd like to somehow call method:
assignPot(FOUL(2, BLUE(5), SWITCH))
From String:
"FOUL(2, BLUE(5), SWITCH)"
The only workaround I can think of is to split the string and create a when -> then function to get actual classes from strings, but I wondered if there's a more concise way for this.
This is not what you want to do. You should design your app in a way that prevents users from providing input similar to actual code.
However, you can achieve this. Complex parsings like this oftenly use regex-based approaches.
As you said, you should map your string part to class. If your PotType is enum, you can do something like
val re = Regex("[^A-Za-z\s]")
val reNumbers = Regex("[^0-9\s]")
// get classes
val classNames = originalString.replace(re, "").split(" ")
// get their constructor numerical arguments
val classArgs = originalString.replace(reNumbers, "").split(" ")
After that you can implement mapping with when expression. You probably will use some collection of Any type.
As you see, this sadly leads you to parsing code by code. Concise way to solve is to implement your own script compiler/interpreter and use it in your application :) That will later lead you to dealing with security breaches and so on.
If you are logging problematic method calls and want to repeat them immediately after issue is submitted, you probably want to programatically save the calls to lambdas and call them when you receive an issue log.
I have this sample data class:
data class Car ( var id: String )
Now I can create a fun as this:
fun doWhatever(id: String){}
My problem is that if my customer then tells me that Id is an int, I have to change it in both places.
So what I want is to set Car.id type as refence in fun doWhatever, something like this:
fun doWhatever(id: propertyTypeOfCarId){}
So I if the customer changes type, I only have to change it in the class.
I read all kind of posts, but I wasnt able to find the answer. Any idea how to achieve it?
If this isn't something you expect to be doing regularly, consider just using the refactoring tools the IDE provides. You code to handle a specific set of data, and if the structure of that data changes, you have to adapt the code to fit it. Baking in a bunch of "what if" functionality can add complexity, compared to just saying a String is a String and changing it if it ever needs changing, using the tools provided to make that as quick and easy as possible.
But sometimes you need to do this kind of thing, and Kotlin has some nice language features it can be worth using, like type aliases:
typealias CarId = String
data class Car(var id: CarId)
fun doWhatever(id: CarId){}
Two benefits here: the actual type is only defined in one place, so you can change that String to an Int without needing to change anything else - except stuff that relied on the ID being a String specifically of course
The other benefit is you're actually adding some semantic information by using that very specific type. That function isn't supposed to just take any old String - it's specifically meant to handle CarIds. It tells you what it's for, and that can make your code a lot easier to understand
(The function will accept Strings, because CarId is just an alias - an alternative name for a String - so it's not a way to enforce structure on your code, just a way to make it nicer to read and write. You can't define a new type that is a String in Kotlin unfortunately)
If the number of id types you support is limited, you can simply use method overloading:
fun doWhatever(id: String){}
fun doWhatever(id: Int){}
// etc.
Alternatively, you can use a reified generic parameter in your method to support any number of types:
inline fun <reified T> doWhatever(id: T) {
when (T::class) {
Int::class -> {}
String::class -> {}
}
}
I'm trying to support game controller input in my app, I should be able to receive the input when in focus of any element of the app. By the way it is not a game.
I have tried following this guide from the android developer documentation to no avail.
The problem I am facing is that I cannot override the onKeyDown function.
My only knowledge is that I need to override this function in either a custom view or activity, but this is what I am having trouble with.
Here is the sort of code I am attempting.
class customView(context:Context) : View(context){
override fun onKeyDown(...){
// Code to handle keydown
}
}
I am getting an error saying something about onKeyDown not being a method of the view class (sorry I'm not at my computer at the moment so I don't know the exact error)
Just as another note I have also looked at this about custom views and I don't really understand how I should go about implementing controller input. For example if I was to create a new view, I would prefer to override something like a fragment which would allow me to have controller input across the entire app. Would it work better overriding the activity?
I'm new to android and kotlin development, so I'm sorry if this is really simple.
Thanks
You forgot the return type
class customView(context: Context) : View(context) {
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return super.onKeyDown(keyCode, event)
}
}
EDIT
To answer your question in the comments, in order to add this view to an XML layout your would need to do something like this
<package.of.my.costumview.customView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Today while programming I found some odd behaviour in Kotlin. I could easily go around it, but I wonder if there is some reason to it or if it is a bug in Kotlin.
I have the following interface of a delegate which delegates the showing of a dialog to the Activity.
interface ViewModelDelegate {
fun showWarningDialog(textResource: Int)
}
I want to implement it as following in the Activity. Since I know I can only do it with a context and the Activity.getContext() may return null, I wrap the code in context?.let
override fun showWarningDialog(textResource: Int) = context?.let {
//show dialog
}
However this gives me a compile error:
Return type of 'showWarningDialog' is not a subtype of the return type of the overridden member 'public abstract fun showWarningDialog(textResource: Int): Unit defined in com.some.class.path'
Which really confused me, because I don't want to return anything. So since let returns whatever the function inside returns, I was wondering if I could fix it by writing a version of let which does not return anything.
fun <T, R> T.myLet(block: (T) -> R) {
let(block)
}
However this did not remove the compiler error. I found then that the mouseover text over the error gives more information (would be nice if the compiler did). It says:
Return type is 'Unit?', which is not a subtype of overridden
Now that tells me more about the problem. Because the function context?let call may not happen, it could return null. Now there are multiple ways to go around this. I could add ?: Unit too the end of the function call or I could define showWarningDialog to return Unit? which will allow me to call it just fine in most cases. However none of these solutions are desireable. I will probably just make a normal method and call the let inside of that instead of delegating the call to it. Costs me another level of indentation and an extra vertical line:
override fun showWarningDialog(textResource: Int) {
context?.let {
//show dialog
}
}
My question is, is this behaviour intended? Why or when would this be useful that a function that returns Unit cannot be delegated to an optional function call. I am very confused by this behaviour.
Single expression function
fun foo() = <expression>
by language design is equivalent to
fun foo(): <ReturnType> {
return <expression>
}
And because Unit? is not a not a subtype of Unit, you can't return it in from a function, which returns Unit. In this sense Unit just another type in the type system, it's not something magical. So it works just as it's supposed to work with any other type.
Why or when would this be useful that a function that returns Unit cannot be delegated to an optional function call.
So basically the question is why language designers did not created a special handling to accept Unit? from a function declaring Unit as a return type. I can think about a few reasons:
It requires to create this special handling in the compiler. Special cases lead to bugs, break slim language design and complicate documentation.
As it had to be a special case, it would be not really clear and predictable for programmers. Currently it works in the same way for all types, no special treatments. It makes the language predictable, you don't need to check the documentation for every type to see if it's treated specially.
It also adds some additional safety, so to make you notice that your expression can actually skip the calculation.
So trying to summarize, I would say making this case work does not add much of value but can potentially bring some issues. That's probably why they did not add it to the language.
lets discuss this case when you have return type for example String
interface someInterface{
fun somFun():String
}
class someClass : someInterface {
var someString:String? = null
override fun somFun()=someString?.let {
//not working
it
}
override fun somFun()=someString?.let {
//working
it
}?:""
}
so what we see that when parents return type is String you cannot return Strin? it is jus kotlins nullSafety ,
what is different when you don't have return type ? lets change the code above a little
interface someInterface{
fun somFun():String
fun unitFun()
}
class someClass : someInterface {
var someString:String? = null
override fun unitFun() {
//if it is possible to return null in here
}
override fun somFun()=someString?.let {
val someresult = unitFun().toString() //you will get crash
it
}?:""
}
now we have another function without return type (unitFun Unit)
so if you can return Unit? in your subclass it will cause a crash when you want to use the result of method because it is defined asUnit and you dont need any null checks.
generally it means Unit is also type and you need to keep it null safe .
Hello to all Android Developers, I need to clarify a doubt in relation to the management of dynamic resources in Android applications.
I need my application to use the translations returned by my backend depending on the language configured on the phone.
I wanted to implement it in an elegant way working on a custom LayoutInflater that applies a ViewTransformer depending on the type of graphic component.
Each ViewTransformer will only collect the identifier (for example #id/landing_welcome_text) and make the next call:
val value = attrs.getAttributeValue(index)
if (value != null && value.startsWith("#")) {
val text = view.context.resources.getString(attrs.getAttributeResourceValue(index, 0))
setTextForView(view, text)
}
A ContextWrapper has been implemented that returns my custom LayoutInflater and a Resource implementation
override fun getSystemService(name: String): Any {
return if (Context.LAYOUT_INFLATER_SERVICE == name)
CustomLayoutInflater(
LayoutInflater.from(baseContext),
this,
viewTransformerManager
)
else
super.getSystemService(name)
}
override fun getResources(): Resources = customResources
The problem is that overwriting the behavior of the Resources class is considered a deprecated strategy.
As the documentation says:
This constructor is deprecated. Resources should not be constructed by
apps. See Context.createConfigurationContext(Configuration).
class CustomResourcesWrapper constructor(
res: Resources,
private val languageStringRepo: ILanguageStringRepo
): Resources(res.assets, res.displayMetrics, res.configuration) {
#Throws(Resources.NotFoundException::class)
override fun getString(id: Int): String {
val value = getStringFromRepository(id)
return value ?: super.getString(id)
}
}
Does anyone know how I can get the same functionality without overwriting the Resources class?
Thank you very much for your help :)
I was looking into the same thing some time ago, in the end our team decided to go with Lokalise SDK.
From what I found out, overriding resources is the only way to do it. And even then it still doesn't cover all the cases, like mentioned in Lokalise documentation:
Some views are not supported when inflating from XML (Action bar, Menu
items, Android preferences, may be others), but you can still get the
latest translations via getString(), getText(), getQuantityString()
and other system methods, and set the content of these views
programmatically.
I saw a similar implementation in this library https://github.com/hamidness/restring although it wasn't nearly as complete as Lokalise. You can see how Lokalise is implemented if you include their library and switch to Project view in Android Studio, expand External Libraries and find com.lokalise.android, then you can see the decompiled .class files:
As for the constructor being deprecated - they deprecated it for the purpose of recreating the Resources when you need them for a different Configuration. But Context.createConfigurationContext doesn't let you override the source of the strings provided by resources, so I don't see any alternative.