Here is a text box
<EditText
android:id="#+id/textBox"
android:width="150px"
android:layout_width="128dp"
android:layout_margin="12dp"/>
Here's some code.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main) // Unresolved reference activity_main
val tb = findViewById(R.id.textBox) as EditText
tb .addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
Toast.makeText(
this#MainActivity,
"Text changed.",
Toast.LENGTH_SHORT
).show()
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
}) }
}
The findViewById doesn't work because Unresolved reference textBox.
What's going on?
None of the examples I've found online work.
This is rubbish!
Why is Android development so exceptionally difficult?
you have to add this back : setContentView(R.layout.activity_main)
why ? setContentView(R.layout.yourLayoutName) is how you associate a layout file to an activity. think of it as connecting the xml you made in the layout to the activity. when you leave out the setContentView, your activity has no layout at all.
then, when it says it's unresolved, you have use the import:
import your.package.name.R (you can usually use alt+enter to bring up these types of suggestions for you)
just start typing setContentView(R.layout.activity_main) then, there should be a line underneath the letter R, just click to the right of it and use alt+ enter to bring up suggestions for imports.
Additional info :
The R class is generated automatically from the application's resources, It contains the ids for the majority of resources created underneath the res folder
Entirely irrlevant note :
Why is Android development so exceptionally difficult?
What's normal for the spider is chaos for the fly :)
Please uncomment setContentView(R.layout.activity_main)from your activity. In kotlin you do not need to explicitly call findViewById. You can simply do this.
textBox.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
Toast.makeText(
this#MainActivity,
"Text changed.",
Toast.LENGTH_SHORT
).show()
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
}) }
Related
In my application I want use EditText and I want after user write on keyboard add suffix text into EditText.
I write below codes, but when user write on keyboard application has freeze!
loginPage4SelectTxt.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable?) {
loginPage4SelectTxt.setText("$p0 Kg")
}
})
How can I fix it?
Whenever the contents of loginPage4SelectTxt changes, those *Changed callbacks fire in order. What are you doing in the last one?
You're changing the contents, which makes the whole thing start over, which makes the whole things start over, forever and ever. You have to be careful about making changes to an EditText inside its own TextWatcher, or you can end up in an infinite loop
It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively.
So you need a way to ignore the changes you're causing with your "update", and only respond to events triggered by actual text entry. You can do that with an updating flag (or whatever you want to call it):
loginPage4SelectTxt.addTextChangedListener(object : TextWatcher {
// use this to track whether an update is in progress,
// so we can avoid retriggering it
var updating = false
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { }
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { }
override fun afterTextChanged(p0: Editable?) {
// skip if an update is happening - this avoids the infinite loop
if (!updating) {
// we're doing an update - set the flag so we don't end up
// back in here
updating = true
// this will trigger the TextWatcher callbacks -immediately-, this code
// won't continue until those are finished
loginPage4SelectTxt.setText("$p0 Kg")
// text is changed and the resulting callbacks have finished - we're done
// updating, so set it to false so the next change will be handled properly
updating = false
}
}
})
is it possible to prevent kotlin from changing parameter names in functions in implemented interfaces ?
for example in this implemented spinner AdapterView.OnItemSelectedListener:
kotlin changes default parameter names :
parent: AdapterView<*>, view: View, position: Int, id: Long
to
p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
}
override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
i know it's because kotlin trying to decrease java boilerplate code but sometimes it makes code becomes confusing.
I am trying to make it so that a progress bar that I put in my edittext field will spin after the user has typed in text. The progress bar should continue to spin until the user has not typed in any more text for one second. (If the user keeps typing in text, the progress bar should keep spinning.) I am using a textWatcher:
et_username_username.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(p0: Editable?) {}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
pb_username_progress_bar.visibility = View.VISIBLE
val updatedText = p0.toString().trim().toLowerCase()
CoroutineScope(IO).launch{
delay(1000)
pb_username_progress_bar.visibitlity = View.INVISIBLE
//updates UI based on firebase database code
}
}
})
However, when I run this, the coroutine just runs on a different thread every time so the progress bar goes away when the user keeps typing for over a second.
How do I make it so that the progress bar will stay there when the user keeps typing, are coroutines the best way or is there another way??
(It should look a lot like instagram when you create a new account, how it has the spinning progress bar when making username)
You can use following code snippet as solution. It will solve your problem.
edit_search.addTextChangedListener(object : TextWatcher {
private var searchFor = ""
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val searchText = s.toString().trim()
if (searchText == searchFor)
return
searchFor = searchText
progress_bar.visibility = View.VISIBLE
CoroutineScope(IO).launch {
delay(1000)
if (searchText != searchFor)
return#launch
progress_bar.visibility = View.INVISIBLE
}
}
})
Happy Coding :)
I can't call function of my class from object inside this class.
How should i do this ?
class LoginActivity: AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
}
private fun disableLoginButton(){
button_login.isEnabled = false
}
private object textChangeListener: TextWatcher{
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
//Here i cannot call function
disableLoginButton() // unresolved reference.
}
}
}
But when i call LoginActivity().disableLoginButton() instead disableLoginButton()it's visible, but fails with
NullPointerException
on login_button
Try this :
class LoginActivity: AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
editTextSample.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int) {
disableLoginButton()
}
})
}
}
private fun disableLoginButton(){
button_login.isEnabled = false
}
EDIT: Doesn't work
From jetbrains team:
In Java and Kotlin, "inner" means "capturing the outer instance", where as "nested" means simply declared inside something else. Java's static classes are only nested, non-static nested classes are inner. In Kotlin you have to explicitly declare something as "inner" (we reversed the Java's convention). So, your object is not inner, btu only nested. And no named object can be inner, in fact: named objects are singletons, so the can not depend on any kind of outer instance.
Try specifying the object as inner:
private inner object textChangeListener: TextWatcher{
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int {
//Here i cannot call function
disableLoginButton() // unresolved reference.
}
}
This should allow you to access the outer scope.
I am using a tag system similar to SO, and instead of forcing the user to find the dash in their keyboard I want space to automatically be translated to a dash.
I am trying to implement it with this textWatcher, but the app doesn't let me type the space bar (it kinda flashes but nothing happens.
imageTagsInput.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
imageTagsInput.removeTextChangedListener(this)
imageTagsInput.setText(imageTagsInput.text.toString().replace(" ","-"))
imageTagsInput.addTextChangedListener(this)
imageTagsInput.setSelection(imageTagsInput.length())
}
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
})
And this is the xml of the EditText:
android:digits="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789- "
Add something like this in afterTextChanged
String result = s.toString().replaceAll(" ", "-");
if (!s.toString().equals(result)) {
ed.setText(result);
ed.setSelection(result.length());
// alert the user
}
For more info see this answer