Decrease function in Kotlin - android

Hey, I have been trying to add decrease function in my android button counter app. There are three buttons(clear, increase, decrease) in my app. Increase is for increasing the counter, decrease is for decreasing the counter and clear is for clearing the textview. i am new here in android. So help me to write the code in kotlin
button?.setOnClickListener(object :View.OnClickListener {
override fun onClick(v: View?) {
numTimeClicked += 1
textview?.append("\n The button got tapped $numTimeClicked time")
if (numTimeClicked != 1){
textview?.append("s")
}
}
})
clear?.setOnClickListener(object :View.OnClickListener{
override fun onClick(v: View?) {
if (numTimeClicked <= 100){
textview?.text = ""
}
}
})
Decrease?.setOnClickListener(object :View.OnClickListener{
override fun onClick(v: View){
if (numTimeClicked >= 1 ){
numTimeClicked -= 1
textview?.append(numTimeClicked.toString())
}
}
})
}
private var userInput:EditText? = null
private var button:Button? = null
private var textview:TextView? = null
private var clear:Button? = null
private var Decrease:Button? = null
private var numTimeClicked = 0
}

fun decreasenumber(var numTimeClicked : Int
) : Int{
numTimeClicked--
return numTimeClicked
}

just replace this line
textview?.append(numTimeClicked.toString())
to
textview?.text = "" + numTimeClicked
append behaves like this: 3 -> 32 -> 321, I think your purpose is to replace not append

Related

Why is my List not being recognized as it has been initialized in onDraw()?

I have initialized my List in the function below in MainActivitywith DataPoint(data class in GraphView)
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var graph_view = GraphView(this)
graph_view.setData(generateRandomDataPoints())
}
fun generateRandomDataPoints(): List<GraphView.DataPoint> {
val random = Random()
return (0..20).map {
GraphView.DataPoint(it, random.nextInt(50) + 1)
}
}
}
GraphView
private val dataSet = arrayListOf<DataPoint>()
private var xMin = 0
private var xMax = 0
private var yMin = 0
private var yMax = 0
private val dataPointPaint = Paint().apply {
color = Color.BLACK
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
Log.e("D SIze", dataSet.size.toString())
for(i in 0 until dataSet.size){
val realX = dataSet[i].xVal.toRealX()
val realY = dataSet[i].yVal.toRealY()
Log.e("TAG", realX.toString())
Log.e("TAG", realY.toString())
Log.e("TAG", "NOT BEingf claeed")
canvas.drawCircle(realX, realY, 17f, dataPointPaint)
}
}
fun setData(newDataSet: List<DataPoint>) {
Log.e("TAG", newDataSet.size.toString())
xMin = newDataSet.minByOrNull { it.xVal }?.xVal ?: 0
xMax = newDataSet.maxByOrNull { it.xVal }?.xVal ?: 0
yMin = newDataSet.minByOrNull { it.yVal }?.yVal ?: 0
yMax = newDataSet.maxByOrNull { it.yVal }?.yVal ?: 0
dataSet.clear() // clear if any point are entered
dataSet.addAll(newDataSet) // add all points fro newDataSet
for(i in 0 .. dataSet.size-1){
Log.e("!!!!", dataSet[i].toString() )
}
invalidate()
}
private fun Int.toRealX() = toFloat() / xMax * width
private fun Int.toRealY() = toFloat() / yMax * height
data class DataPoint(
val xVal: Int,
val yVal: Int)
}
All of my logs work as expected and print's what is expected.
But when onDraw() is called from the invalidate() in the setData() function the log at the start returns 0. Which is why the for loop in onDraw() is never called and no points dots are being printed to the canvas?
I do not know why as all my other logs show that the data has been added for example the for loop in setData() prints
DataPoint(xVal=1, yVal=20)
DataPoint(xVal=3, yVal=37)
DataPoint(xVal=4, yVal=39)
....
Why is this and how can I solve it please?

How to use SetOnClickListener on a programmatic ScrollView Android Kotlin

I created a scrollView programmaticaly that contains 20 views each with an image and a text.
I have two questions :
1 - is the id assignment correct and is my setOnClickListener correct?
2 - By which method onClick can I know which view of the scrollView the user has clicked?
See my code below
private var integerList: MutableList<Int>? = mutableListOf()
private var cellNo: MutableList<String>? = mutableListOf()
private var sv_mvmtChoosed = ""
private fun showSpinner() {
/* SCROllL VIEW */
var linearLayout: LinearLayout? = null
linearLayout = findViewById(R.id.linear1)
val layoutInflater = LayoutInflater.from(this)
var randIndex = 0
for (posIndex in 0..19) {
val rand = Random()
randIndex = rand.nextInt(20)
while (integerList!!.contains(randIndex)) {
randIndex = rand.nextInt(20)
}
integerList!!.add(randIndex)
// Create the view...
val view: View = layoutInflater.inflate(R.layout.scroll_bckgrnd, linearLayout, false)
// give it an id
view.id = generateViewId()
view.setOnClickListener(this)
cellNo!!.add(view.id.toString())
println(cellNo)
//... then populate it with image and text
val iv = view.findViewById<ImageView>(R.id.iv)
iv.setImageResource(sv_photoImage[randIndex])
val tv = view.findViewById<TextView>(R.id.tv)
tv.text = sv_photoName[randIndex]
linearLayout?.addView(view)
}
// which view the user did select?
fun onClick(view: View?) {
when (view!!.id) {
??? -> doSomething
}
}
}
Any idea to get me back on track will be welcome.
Its probably better to make a new OnClickListener for every view.
view.setOnClickListener(this)
needs to be this
view.setOnClickListener {
// do something
}
or
view.setOnClickListener(createOnClickListner())
fun createOnClickListner():View.OnClickListener{
return object :View.OnClickListener{
override fun onClick(view : View) {
//do something with the view that was clicked
}
}
}
Thanks a lot avalerio.
I finally found a solution as follow :
I replaced :
// give it an id
view.id = generateViewId()
view.setOnClickListener(this)
cellNo!!.add(view.id.toString())
println(cellNo)
with :
// give it an id
view.id = posIndex
view.setOnClickListener(this)
then I did this :
// the onClickListener for my 20 images/text
override fun onClick(view: View?) {
when (view!!.id) {
// Now de position clicked on the ScrollView
in 0..19 -> didHeSucceeded(view!!.id)
}
}
And use the result:
private fun didHeSucceeded(scrllPos: Int) {
// TODO: close de scrollView, how ? :-)
spinnerChoice = nameOfTechScrollVw[scrllPos]
succes = (!allreadyChoosedArray.contains(spinnerChoice)) && (currentArray.contains(spinnerChoice
))
if (succes) {
...
...
}
It works perfectly

How do I ensure lateinit variable initialization before it is needed?

I have an app that launches the majority of the time, but every 7 or so launches it crashes with the error:
kotlin.UninitializedPropertyAccessException: lateinit property weekdayList has not been initialized
This is a clear error, I'm just not sure how to ensure the variable is initialized early enough in the context of my app.
Things I have tried
I tried moving variables around, making "inner" and "outer"
variables, one within onCreate and an underscore led variable as
the class variable.
Changing the viewmodel so that it will wait until the call to the db has finished (I
couldn't make this work, but mostly because I wasn't sure how to do it).
I think the problem is in the onCreate function, and that the weekday observe isn't setting the value of the variable faster than the task observe (where the weekdayList variable is needed) is called?
Edit 1
I referenced this but I end up with a similar error
java.lang.IndexOutOfBoundsException: Empty list doesn't contain element at index 1.
Edit 2
I understand how lateinit variables and nullables work at this point, I want to try and clarify this a little better.
The variable weekdayList needs to be initialized to the correct list before I hit the observe for the taskList, otherwise the app will crash.
I have tried setting the variable to be nullable, and Iend up with:
skipping parts of the program when it's null (not an option)
crashing with a null pointer exception (if set to non-nullable)
no tasks get assigned to any day, which means no recyclerviews get updated, thus making the app appear to contain no tasks when it does.
weekday buttons that don't work because there is no weekdayList for them to compare against to launch the next activity
My problem doesn't stand in figuring out if it's null or not, it's trying to guarantee that it won't be null.
Sorry for the confusion
Main Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val plannerViewModel: PlannerViewModel by viewModels {
PlannerViewModelFactory((application as PlannerApplication).repository)
}
private var weekdayList: List<Weekday> = listOf()
private var taskList: List<Task> = listOf()
private var taskDayList = mutableListOf<Task>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val clearButtonText = binding.clearCardText
val sundayButtonText = binding.sundayCardText
val mondayButtonText = binding.mondayCardText
val tuesdayButtonText = binding.tuesdayCardText
val wednesdayButtonText = binding.wednesdayCardText
val thursdayButtonText = binding.thursdayCardText
val fridayButtonText = binding.fridayCardText
val saturdayButtonText = binding.saturdayCardText
val sundayRv: RecyclerView = binding.sundayRv
val sundayAdapter = TaskRvAdapter(null)
sundayRv.adapter = sundayAdapter
sundayRv.layoutManager = LinearLayoutManager(this)
val mondayRv: RecyclerView = binding.mondayRv
val mondayAdapter = TaskRvAdapter(null)
mondayRv.adapter = mondayAdapter
mondayRv.layoutManager = LinearLayoutManager(this)
val tuesdayRv: RecyclerView = binding.tuesdayRv
val tuesdayAdapter = TaskRvAdapter(null)
tuesdayRv.adapter = tuesdayAdapter
tuesdayRv.layoutManager = LinearLayoutManager(this)
val wednesdayRv: RecyclerView = binding.wednesdayRv
val wednesdayAdapter = TaskRvAdapter(null)
wednesdayRv.adapter = wednesdayAdapter
wednesdayRv.layoutManager = LinearLayoutManager(this)
val thursdayRv: RecyclerView = binding.thursdayRv
val thursdayAdapter = TaskRvAdapter(null)
thursdayRv.adapter = thursdayAdapter
thursdayRv.layoutManager = LinearLayoutManager(this)
val fridayRv: RecyclerView = binding.fridayRv
val fridayAdapter = TaskRvAdapter(null)
fridayRv.adapter = fridayAdapter
fridayRv.layoutManager = LinearLayoutManager(this)
val saturdayRv: RecyclerView = binding.saturdayRv
val saturdayAdapter = TaskRvAdapter(null)
saturdayRv.adapter = saturdayAdapter
saturdayRv.layoutManager = LinearLayoutManager(this)
// Setting day card names
clearButtonText.text = "Clear"
sundayButtonText.text = "Sun"
mondayButtonText.text = "Mon"
tuesdayButtonText.text = "Tue"
wednesdayButtonText.text = "Wed"
thursdayButtonText.text = "Thu"
fridayButtonText.text = "Fri"
saturdayButtonText.text = "Sat"
sundayButtonText.text = "Sun"
plannerViewModel.allWeekdays.observe(this, {
weekdayList = it
})
plannerViewModel.allTasks.observe(this, { tasks ->
taskList = tasks
taskDayList = mutableListOf()
for (i in 1..7) {
taskDayList = sortTasks(weekdayList[i], taskList)
when (i) {
1 -> {
sundayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.sundayInner,
binding.sundayCardText, sundayRv, binding.sundayNoTasks)
}
2 -> {
mondayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.mondayInner,
binding.mondayCardText, mondayRv, binding.mondayNoTasks)
}
3 -> {
tuesdayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.tuesdayInner,
binding.tuesdayCardText, tuesdayRv, binding.tuesdayNoTasks)
}
4 -> {
wednesdayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.wednesdayInner,
binding.wednesdayCardText, wednesdayRv, binding.wednesdayNoTasks)
}
5 -> {
thursdayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.thursdayInner,
binding.thursdayCardText, thursdayRv, binding.thursdayNoTasks)
}
6 -> {
fridayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.fridayInner,
binding.fridayCardText, fridayRv, binding.fridayNoTasks)
}
7 -> {
saturdayAdapter.submitList(taskDayList)
toggleVisibility(taskDayList, binding.saturdayInner,
binding.saturdayCardText, saturdayRv, binding.saturdayNoTasks)
}
}
}
})
}
private fun toggleVisibility(taskDayList: List<Task>, inner: ConstraintLayout,
cardText: View, rv: RecyclerView, noTask: View) {
if (taskDayList.count() == 0 ) {
val newConstraintSet = ConstraintSet()
newConstraintSet.clone(inner)
newConstraintSet.connect(noTask.id, ConstraintSet.TOP,
cardText.id, ConstraintSet.BOTTOM)
newConstraintSet.applyTo(inner)
newConstraintSet.connect(cardText.id, ConstraintSet.BOTTOM,
noTask.id, ConstraintSet.TOP)
newConstraintSet.applyTo(inner)
rv.visibility = View.GONE
noTask.visibility = View.VISIBLE
Log.i("this", "ran zero")
} else {
val newConstraintSet = ConstraintSet()
newConstraintSet.clone(inner)
newConstraintSet.connect(rv.id, ConstraintSet.TOP,
cardText.id, ConstraintSet.BOTTOM)
newConstraintSet.applyTo(inner)
newConstraintSet.connect(cardText.id, ConstraintSet.BOTTOM,
rv.id, ConstraintSet.TOP)
newConstraintSet.applyTo(inner)
rv.visibility = View.VISIBLE
noTask.visibility = View.GONE
Log.i("this", "ran else")
}
}
private fun sortTasks(day: Weekday, tasks: List<Task>): MutableList<Task> {
val newAdapterList = mutableListOf<Task>()
tasks.forEach {
if (it.weekdayId == day.id) {
newAdapterList.add(it)
}
}
return newAdapterList
}
private fun startWeekdayActivity(day: Weekday) {
val intent = Intent(this, WeekdayActivity::class.java)
intent.putExtra("dayId", day.id)
this.startActivity(intent)
}
private fun clearDb(taskList: List<Task>) {
val alertDialog: AlertDialog = this.let { outerIt ->
val builder = AlertDialog.Builder(outerIt)
builder.apply {
setPositiveButton("Clear",
DialogInterface.OnClickListener { dialog, id ->
if (taskList.count() == 0) {
Toast.makeText(context, "No tasks to clear", Toast.LENGTH_SHORT).show()
} else {
plannerViewModel.deleteAllTasks()
Toast.makeText(context, "Tasks cleared", Toast.LENGTH_SHORT).show()
}
})
setNegativeButton("Cancel",
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
}
.setTitle("Clear tasks?")
.setMessage("Are you sure you want to clear the weeks tasks?")
builder.create()
}
alertDialog.show()
}
private fun checkDay(dayIn: String, weekdayList: List<Weekday>) {
weekdayList.forEach {
if (dayIn == "clear_card" && it.day == "Clear") {
clearDb(taskList)
} else {
val dayInAbr = dayIn.substring(0, 3).toLowerCase(Locale.ROOT)
val dayOutAbr = it.day.substring(0, 3).toLowerCase(Locale.ROOT)
if (dayInAbr == dayOutAbr) {
startWeekdayActivity(it)
}
}
}
}
fun buttonClick(view: View) {
when (view.id) {
R.id.clear_card -> checkDay(view.context.resources.getResourceEntryName(R.id.clear_card).toString(), weekdayList)
R.id.sunday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.sunday_card).toString(), weekdayList)
R.id.monday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.monday_card).toString(), weekdayList)
R.id.tuesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.tuesday_card).toString(), weekdayList)
R.id.wednesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.wednesday_card).toString(), weekdayList)
R.id.thursday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.thursday_card).toString(), weekdayList)
R.id.friday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.friday_card).toString(), weekdayList)
R.id.saturday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.saturday_card).toString(), weekdayList)
}
}
}
Viewmodel
class PlannerViewModel(private val repository: DbRepository) : ViewModel() {
val allWeekdays: LiveData<List<Weekday>> = repository.allWeekdays.asLiveData()
val allTasks: LiveData<List<Task>> = repository.allTasks.asLiveData()
fun insertWeekday(weekday: Weekday) = viewModelScope.launch {
repository.insertWeekday(weekday)
}
fun insertTask(task: Task) = viewModelScope.launch {
repository.insertTask(task)
}
fun deleteTask(task: Task) = viewModelScope.launch {
repository.deleteTask(task)
}
fun deleteAllTasks() = viewModelScope.launch {
repository.deleteAllTasks()
}
}
class PlannerViewModelFactory(private val repository: DbRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(PlannerViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return PlannerViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
A variable declared as lateinit just means that you are sure that when the object is dereferenced it will not be null. In your case you are calling a method from weekdayList object before it is assigned a value. It is important to understand the concept clearly and why your code works.
Happy Coding!
You can use the "isInitialized" method, for checking "lateinit" variable is initialized or not.
Please refer the below article for the this-
https://blog.mindorks.com/how-to-check-if-a-lateinit-variable-has-been-initialized
lateinit is a way for you to have a var without an initial value when you declare it. It's a nice way to avoid taking something that will never be null, and making it nullable (and having to null check it forever) just so you can temporarily set it to null as a placeholder that nothing will ever see.
What you're doing is promising the compiler "ok, I'm not going to provide a value when the class is constructed, but I promise I'll set it to something before anything tries to read it". You're telling the compiler to trust you, that you know how your code works, and you can guarantee it'll all be ok.
Your problem is that it seems you can't guarantee that things won't try to read that property before you write to it. Your state can either be "has a value", or "doesn't have a value", and the rest of your code could encounter either state.
The "no value" state is basically null, so you should probably make the variable nullable instead, and initialise it as null. Kotlin has all that nice null-safety stuff to help your code handle it, until you do get a value. lateinit seems like the wrong tool for the job, even if you check ::isInitialized it's just making your life a lot harder when the null-checking stuff is right there!
Use lazy properties , refer to this doc for more informations:
assuming weekDayList is the property you want to successfully initialize ->
private var weekDayList: List<WeekDay> by lazy {
//return your first value
listOf<WeekDay>()
}
Here is a useful link about LifeCycleAware Lazy properties: blog Although, it is not required.
A solution with help from cactustictacs in the comments.
I moved a lot of the list dependency to a new function called setAdapterList. this allows both observes to run the function, and only the one with both lists initialized will run the code contained. I kept the variables lateinit and it seems to be working so far!
The Main Change in Main Activity
...
private fun setAdapterLists(adapterList: List<TaskRvAdapter>, rvList: List<RecyclerView>) {
if (this::weekdayList.isInitialized && this::taskList.isInitialized) {
adapterList.forEach {
taskDayList = mutableListOf()
val i = adapterList.indexOf(it)
taskDayList = sortTasks(weekdayList[i + 1], taskList)
Log.i("rvli", rvList[i].toString())
when (i) {
0 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.sundayInner,
binding.sundayCardText, rvList[i], binding.sundayNoTasks)
}
1 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.mondayInner,
binding.mondayCardText, rvList[i], binding.mondayNoTasks)
}
2 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.tuesdayInner,
binding.tuesdayCardText, rvList[i], binding.tuesdayNoTasks)
}
3 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.wednesdayInner,
binding.wednesdayCardText, rvList[i], binding.wednesdayNoTasks)
}
4 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.thursdayInner,
binding.thursdayCardText, rvList[i], binding.thursdayNoTasks)
}
5 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.fridayInner,
binding.fridayCardText, rvList[i], binding.fridayNoTasks)
}
6 -> {
adapterList[i].submitList(taskDayList)
toggleVisibility(taskDayList, binding.saturdayInner,
binding.saturdayCardText, rvList[i], binding.saturdayNoTasks)
}
}
}
}
}
...

Getting NumberFormatException in onSavedInstanceState() method [duplicate]

This question already has answers here:
How can I prevent java.lang.NumberFormatException: For input string: "N/A"?
(6 answers)
Closed 2 years ago.
I am using onSavedInstanceState() method so that after after rotating device my textview should not lost its value but i'm getting crash that i've mentioned in activity.
Following is my activity
class SavedInstanceActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_saved_instance)
imgPlus.setOnClickListener {
if (tvText.text.toString().toInt() >= 10)
tvText.text = "10"
else
tvText.text = tvText.text.toString().toInt().plus(1).toString()
}
imgMinus.setOnClickListener {
if (tvText.text.toString().toInt() <= 0)
tvText.text = "0"
else
tvText.text = tvText.text.toString().toInt().minus(1).toString()
}
if (savedInstanceState != null) {
count = savedInstanceState.getInt("int", 0)
tvText.text = count.toString()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("int", tvText.toString().toInt()) //getting crash here java.lang.NumberFormatException: For input string: "com.google.android.material.textview.MaterialTextView{12c8970 V.ED..... ........ 511,982-570,1084 #7f080174 app:id/tvText}"
Log.d("saved", tvText.toString())
}
}
You are tried to convert textview as string instead of text
Try like beklow...
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("int", tvText.text.toString().toInt())
Log.d("saved", tvText.toString())
}
You are using tvText.toString().toInt() it should be tvText.text.toString().toInt() . Also you need to check if text is empty or not before parsing it to Int . See the code below i have made some modifications.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
imgPlus.setOnClickListener {
if (tvText.text.toString().isNotEmpty() && tvText.text.toString().toInt() >= 10)
tvText.text = "10"
else
tvText.text = tvText.text.toString().toInt().plus(1).toString()
}
imgMinus.setOnClickListener {
if (tvText.text.toString().isNotEmpty() && tvText.text.toString().toInt() <= 0)
tvText.text = "0"
else
tvText.text = tvText.text.toString().toInt().minus(1).toString()
}
if (savedInstanceState != null) {
val count = savedInstanceState.getInt("int", 0)
tvText.text = count.toString()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
if(tvText.text.toString().isNotEmpty())
outState.putInt("int", tvText.text.toString().toInt())
}
I don't recommend relying on a text UI element to store your non-text application state. It's kind of convoluted. I would keep the count as an Int property and sync it with the TextView. Actually, I would put the count in the ViewModel if there was one, but for simplicity:
class SavedInstanceActivity : AppCompatActivity() {
private var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_saved_instance)
imgPlus.setOnClickListener {
count = min(count + 1, 10)
tvText.text = count.toString()
}
imgMinus.setOnClickListener {
count = max(count - 1, 0)
tvText.text = count.toString()
}
if (savedInstanceState != null) {
count = savedInstanceState.getInt("int", 0)
tvText.text = count.toString()
}
}
//...
}
To take it a step further, you could make the property automatically update the text view when it's changed:
class SavedInstanceActivity : AppCompatActivity() {
private var count by Delegates.observable(0) { _, _, _ ->
tvText.text = count.toString()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_saved_instance)
imgPlus.setOnClickListener {
count = min(count + 1, 10)
}
imgMinus.setOnClickListener {
count = max(count - 1, 0)
}
if (savedInstanceState != null) {
count = savedInstanceState.getInt("int", 0)
}
}
//...
}
As for your specific problem, as the other answers have mentioned, it's because you're trying to convert the text without safely checking if it is parseable as an Int, and it's not if it's blank. It is safer to use toIntOrNull() which gives you an Int? to work with instead of throwing an exception when the text is invalid.

How can I control interger_number EditText stop number decrease once 0 reached?

My activity has increase btn, decrease btn, productpoint and integer_number for count.
when I clciked decrease btn, integer_number and productpoint changed negative.
So, I dont want get negative.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
var productpoint = findViewById<TextView>(R.id.productPoint)
var point=0
val inc_val=16000
increase.setOnClickListener {
increaseInteger()
point+=inc_val
productpoint.text = point.toString()+"P"}
decrease.setOnClickListener {
decreaseInteger()
point-=inc_val
productpoint.text = point.toString()+"P"
}
fun increaseInteger() {
display(integer_number.text.toString().toInt() + 1)
}
fun decreaseInteger() {
display(integer_number.text.toString().toInt() - 1)
}
private fun display(number: Int) {
integer_number.setText("$number")
}
}
Assume initial value of integer_number TextView is larger than 0, here is my solution.
fun increaseInteger() {
val newValue = integer_number.text.toString().toInt() + 1
if (newValue > 0 && !decrease.isEnabled) {
decrease.isEnabled = true
}
display(newValue)
}
fun decreaseInteger() {
val newValue = integer_number.text.toString().toInt() - 1
if (newValue <= 0) {
decrease.isEnabled = false
}
display(newValue)
}
Try this
fun decreaseInteger() {
if(integer_number.text.toString().toInt()<=0)
{
display(0)
}
display(integer_number.text.toString().toInt() - 1)
}

Categories

Resources