Typechecking in Kotlin - android

I am a Kotlin newbie. I have a simple app in which I'm trying to sanitise all my input. Everything works in theory, but my app doesn't produce the required output.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editTextWeight = findViewById<EditText>(R.id.weightEditText) as EditText
val editTextHeight = findViewById<EditText>(R.id.heightEditText) as EditText
val calculateButton = findViewById<Button>(R.id.calcButton)
calculateButton.isEnabled = false
val weight = editTextWeight.text.toString().toDoubleOrNull()
val height = editTextHeight.text.toString().toDoubleOrNull()
if (weight != null && height != null ) {
calculateButton.isEnabled = true
calculateButton?.setOnClickListener()
{
val bmi = weight / (height*height )
Toast.makeText(this#MainActivity,
"Your BMI is $bmi", Toast.LENGTH_LONG).show()
}
}
}
}
I have tried to add an else condition ie:
//calculateButton.isEnabled = false
if (weight != null && height != null ) {
//calculateButton.isEnabled = true
calculateButton?.setOnClickListener()
{
val bmi = weight / (height*height )
Toast.makeText(this#MainActivity,
"Your BMI is $bmi", Toast.LENGTH_LONG).show()
}
}else
Toast.makeText(this#MainActivity,
"Please enter both values correctly!", Toast.LENGTH_LONG).show()
The button is clickable, but I get no output from the app.
What am I doing wrong? Is there an app state like in Angular where I can seperate component initialisation from program logic?

You should check the text input when you perform click on your button, in perfect programm your code should look like this :
class MainActivity : AppCompatActivity() {
lateinit var calculateButton: Button
lateinit var editTextWeight: EditText
lateinit var editTextHeight: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
editTextWeight = findViewById(R.id.weightEditText)
editTextHeight = findViewById(R.id.heightEditText)
calculateButton = findViewById(R.id.calcButton)
calculateButton.setOnClickListener()
{
val weight: Double = editTextWeight.text.toString().toDoubleOrNull() ?: 0.0
val height: Double = editTextHeight.text.toString().toDoubleOrNull() ?: 0.0
val bmi = weight / (height * height)
if (bmi.isNaN())
Toast.makeText(this#MainActivity,
"Input error, please try again!", Toast.LENGTH_LONG).show()
else
Toast.makeText(this#MainActivity,
"Your BMI is $bmi", Toast.LENGTH_LONG).show()
}
}
}

Related

I'm having an issue with the calculator that I'm building on Android

I currently have all of the buttons needed. However, the Operators button is not using the character. At the time that you click in one of the operators is not returning anything.
package com.example.mycalculator
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var lastNumeric : Boolean = false
var lastDot : Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun onDigit(view: View){
tvInput.append((view as Button).text)
lastNumeric = true
}
fun onClear(view: View){
tvInput.text = ""
lastNumeric = false
lastDot = false
}
fun onDecimalPoint(view: View){
if (lastNumeric && !lastDot){
tvInput.append(".")
lastNumeric = false
lastDot = false
}
}
fun onEqual(view: View){
if(lastNumeric){
var tvValue = tvInput.text.toString()
var prefix = "="
try {
if(tvValue.contains("-")){
val splitValue = tvValue.split("-")
var one = splitValue[0]
var two = splitValue[1]
if(!prefix.isEmpty()){
one = prefix + one
}
// Check if it is empty or if we have a second minus
tvInput.text = (one.toDouble() - two.toDouble()).toString()
} else if(tvValue.contains("/")){
val splitValue = tvValue.split("/")
var one = splitValue[0]
var two = splitValue[1]
// Check if it is empty or if we have a second minus
if(!prefix.isEmpty()){
one = prefix + one
}
tvInput.text = (one.toDouble() / two.toDouble()).toString()
}else if(tvValue.contains("*")){
val splitValue = tvValue.split("*")
var one = splitValue[0]
var two = splitValue[1]
// Check if it is empty or if we have a second minus
if(!prefix.isEmpty()){
one = prefix + one
}
tvInput.text = (one.toDouble() * two.toDouble()).toString()
}else if(tvValue.contains("+")){
val splitValue = tvValue.split("+")
var one = splitValue[0]
var two = splitValue[1]
// Check if it is empty or if we have a second minus
if(!prefix.isEmpty()){
one = prefix + one
}
tvInput.text = (one.toDouble() + two.toDouble()).toString()
}
}catch (e: ArithmeticException){
e.printStackTrace()
}
}
}
fun onOperator(view: View){
if(lastNumeric && !isOperatorAdded(tvInput.toString())){
tvInput.append((view as Button).text)
lastNumeric = false
}
}
private fun isOperatorAdded(value: String) : Boolean {
return if (value.startsWith("-")){
false
} else value.contains("/") || value.contains("*") || value.contains("+") || value.contains("-")
}
}
Inside of the activity_main, I have that the operator is coming through onClick element call "onOperator."
Example:
<Button
android:id="#+id/btnAdd"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:width="0dp"
android:text="+"
android:onClick="onOperator"
android:layout_margin="5dp"
/>
Does anyone know what is the best way to solve this issue?
what is tvInput? you haven't declared it anywhere, but using in many places... (stripped out code?)
looks like tvInput is a TextView, you are using tvInput.text.toString() in one of your lines
so your if condition in onOperator is wrong
if(lastNumeric && !isOperatorAdded(tvInput.toString())){
you should check text placed in tvInput, not tvInput itself (as View). tvInput.toString() will return some "random" String representing this View, not content of this View. try with this line:
if(lastNumeric && !isOperatorAdded(tvInput.text.toString())){
and get familiar with logging, its crucial... you could put a Log line in onOperator and find out by yourself that these conditions/values are wrong

Decrease function in Kotlin

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

How to run code when resuming an activity after a swipe back gesture from another activity in WearOS?

I have three activities
MainActivity
StartActivity
EndActivity
When the app loads it opens MainActivty, there are two buttons called Start and End. Clicking on Start takes to StartActivity and End takes to EndActivity. From both these activities, I can swipe back to MainActivity. I want to execute code in MainActivity when the others are swiped away and the MainActivity is revealed.
So far I have tried OnResume and OnRestart events with no success. Please suggest something that I can try?
Please note: I am not interested about the Activity from which I come back from. Only need to execute code when the MainActivity is resumed.
MainActivity
class MainActivity : WearableActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnStart = findViewById(R.id.btnStartActivity) as Button
btnStart.setOnClickListener{
//Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
val intent = Intent(this#MainActivity, StartActivity::class.java)
startActivity(intent)
}
val btnEnd = findViewById(R.id.btnEndActivity) as Button
btnEnd.setOnClickListener{
//Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
val intent = Intent(this#MainActivity, EndActivity::class.java)
startActivity(intent)
}
// Enables Always-on
setAmbientEnabled()
}
fun onRestart(savedInstanceState: Bundle?) {
super.onRestart();
val btnStart = findViewById(R.id.btnStartActivity) as Button
btnStart.text = MyApplication.Companion.g_hour_start.toString() +":" + MyApplication.Companion.g_min_start.toString()
}
}
StartActivity
class StartActivity : WearableActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_start)
val pickerStart = findViewById(R.id.timePickerStart) as TimePicker
pickerStart.setIs24HourView(true)
pickerStart.setHour(MyApplication.Companion.g_hour_start)
pickerStart.setMinute(MyApplication.Companion.g_min_start)
pickerStart.setOnTimeChangedListener(TimePicker.OnTimeChangedListener { view, hourOfDay, minute ->
MyApplication.Companion.g_hour_start = hourOfDay
MyApplication.Companion.g_min_start =minute
})
// Enables Always-on
setAmbientEnabled()
}
override fun onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed()
finish()
}
}
EndActivity is similar to StartActivity
Link to Code: Layout and code
If you launch StartActivity and EndActivity using
startActivityForResult (Intent intent, int requestCode)
you will get a callback once they finish (i.e. dismissed by the user and returns to MainActivity)
onActivityResult (int requestCode, int resultCode, Intent data)
Since you don't care about the activity you come back from you can ignore most of the arguments and just execute the code you need to run.
More details can be found in the official documentation.
I got the code to work. But not sure if it is the right way.
Screen record of the App - TimeDifference Screen Record
MainActivity
class MainActivity : WearableActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//Log.d(TAG,"onCreate: called")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyApplication.Companion.g_hour_start =0
MyApplication.Companion.g_min_start = 0
MyApplication.Companion.g_hour_end =0
MyApplication.Companion.g_min_end = 0
val btnStart = findViewById(R.id.btnStartActivity) as Button
btnStart.setOnClickListener{
//Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
val intent = Intent(this#MainActivity, StartActivity::class.java)
startActivity(intent)
}
val btnEnd = findViewById(R.id.btnEndActivity) as Button
btnEnd.setOnClickListener{
//Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
val intent = Intent(this#MainActivity, EndActivity::class.java)
startActivity(intent)
}
// Enables Always-on
setAmbientEnabled()
}
override fun onResume() {
//Log.d(TAG,"onResume: called")
super.onResume();
val btnStart = findViewById(R.id.btnStartActivity) as Button
val btnEnd = findViewById(R.id.btnEndActivity) as Button
val txtCalc = findViewById(R.id.txtResult) as TextView
val StartHour = MyApplication.Companion.g_hour_start
val StartMin = MyApplication.Companion.g_min_start
val EndHour = MyApplication.Companion.g_hour_end
val EndMin = MyApplication.Companion.g_min_end
val DifferenceMinutes : Int
val DiffHour : Int
val DiffMin : Int
if (StartHour + StartMin != 0 ) {
btnStart.text =
StartHour.toString().padStart(2,'0') + ":" + StartMin.toString().padStart(2,'0')
}
if (EndHour + EndMin != 0 ) {
btnEnd.text =
EndHour.toString().padStart(2,'0') + ":" + EndMin.toString().padStart(2,'0')
}
if (StartHour + StartMin != 0 &&
EndHour + EndMin != 0 ){
//txtCalc.textSize = 20f
var TotalStartMinutes = StartHour * 60 + StartMin
var TotalEndMinutes = EndHour * 60 + EndMin
if(TotalEndMinutes> TotalStartMinutes) {
DifferenceMinutes = TotalEndMinutes - TotalStartMinutes
}else{
DifferenceMinutes = TotalStartMinutes - TotalEndMinutes
}
DiffHour = DifferenceMinutes / 60
DiffMin = DifferenceMinutes % 60
if (DiffHour == 0 && DiffMin == 0){
txtCalc.text = "No Difference!!"
}else if (DiffHour == 0){
txtCalc.text = "$DiffMin m"
} else if(DiffMin == 0){
txtCalc.text = "$DiffHour h"
} else{
txtCalc.text = "$DiffHour h and $DiffMin m"
}
}
}
}
StartActivity
class StartActivity : WearableActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_start)
val pickerStart = findViewById(R.id.timePickerStart) as TimePicker
pickerStart.setIs24HourView(true)
pickerStart.setHour(MyApplication.Companion.g_hour_start)
pickerStart.setMinute(MyApplication.Companion.g_min_start)
pickerStart.setOnTimeChangedListener(TimePicker.OnTimeChangedListener { view, hourOfDay, minute ->
MyApplication.Companion.g_hour_start = hourOfDay
MyApplication.Companion.g_min_start =minute
})
// Enables Always-on
setAmbientEnabled()
}
}
For Global Variables
class MyApplication : Application() {
companion object {
var g_hour_start = 0
var g_min_start = 0
var g_hour_end = 0
var g_min_end = 0
}
override fun onCreate() {
super.onCreate()
// initialization code here
}
}
EndActivity is similar to StartActivity
Code and Layout for the WearOS app

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)
}

Check if EditText is empty while calculating numbers

I'm trying to build an age calculator application. When I didn't enter a number in one of the EditTexts and click on calculate Button, my app is crashed! "App has stopped" and click the photo
I tried to set yearbirth.isEmpty() || yearbirth.equals("") || yearbirth == null , but nothing worked.
CODE:-
class MainActivity : AppCompatActivity() {
var yearage:Int?= null
var monthage:Int?= null
var dayage:Int?= null
#SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
buGetAge.setOnClickListener({
val year= Calendar.getInstance().get(Calendar.YEAR)
val month= Calendar.getInstance().get(Calendar.MONTH)
val day= Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
var yearage = year - Integer.parseInt(yearbirth.text.toString()) -1
val monthage:Int?
val dayage:Int?
if (yearbirth== null) {
Toast.makeText(this, "You have to enter your year berth", Toast.LENGTH_LONG).show()
} else {
if (month < Integer.parseInt(monthbirth.text.toString())){
monthage=(Integer.parseInt(monthbirth.text.toString())- month- 12)* -1
}else if (month > Integer.parseInt(monthbirth.text.toString())) {
yearage=year- Integer.parseInt(yearbirth.text.toString())
monthage= (Integer.parseInt(monthbirth.text.toString())- month)* -1
}else {
yearage=year- Integer.parseInt(yearbirth.text.toString())
monthage=0
}
if (day < Integer.parseInt(daybirth.text.toString())){
dayage= (Integer.parseInt(daybirth.text.toString())- day- 30)* -1
}else if (day > Integer.parseInt(daybirth.text.toString())){
dayage= day- Integer.parseInt(daybirth.text.toString())
}else {
dayage=0
}
val a= (yearage* 12)+ monthage
val b= (a * 30)+ dayage
val ageinyears= "$yearage years"
val ageinmonths= "$a months"
val ageindays= "$b days"
txtshow.text = "Your age is $yearage years, $monthage months and $dayage days"
txtshow2.text = "\nYOUR AGE:\nin years:\n\nin months:\n\nin days:"
txtshow3.text = "\n\n$ageinyears \n\n$ageinmonths \n\n $ageindays "
this.yearage=yearage
this.monthage=monthage
this.dayage=dayage
}
})
}
}
Verify that yearbirth.text.toString() is not empty before attempting to parse it into an Integer (and also if it's a valid integer.)
To achieve so, put the line you showed in your code:
var yearage = year - Integer.parseInt(yearbirth.text.toString()) -1
Inside an if verifying that the input is valid, like so:
if(yearbirth.text.toString().matches(Regex("\\d+")))
var yearage = year - Integer.parseInt(yearbirth.text.toString()) -1
You can check for empty Input like this:
newString = Integer.toString(yearbirth).trim();
if (newString.matches("")) {
Toast.makeText(this, "EditText is empty", Toast.LENGTH_SHORT).show();
return;
}

Categories

Resources