package com.example.tipcalculator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import kotlin.text.toFloat as kotlinTextToFloat
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
val tenPerTip: Button = findViewById(R.id.tenPerTipButton)
val fifteenPerTip: Button = findViewById(R.id.fifteenPerTipButton)
val twentyPerTip: Button = findViewById(R.id.twentyPerTipButton)
val customTip: Button = findViewById(R.id.customTipSubmit)
val sumRaw: EditText = findViewById(R.id.billEnter)
val tipOnlyResult: TextView = findViewById(R.id.tipOnlyResult)
val totalResult: TextView = findViewById(R.id.totalResult)
val sumString = sumRaw.toString()
val sumInput = sumString.toInt()
tenPerTip.setOnClickListener{
val sumTotal = sumInput * 1.1
val tipOnly = sumInput * 0.1
tipOnlyResult.text = tipOnly.toString()
totalResult.text = sumTotal.toString()
}
fifteenPerTip.setOnClickListener{
}
twentyPerTip.setOnClickListener{
}
customTip.setOnClickListener{
}
}
}
I was trying to switch the EditText input to a string and from there to a float so that I can do calculations on it. On the line with val sumInput = sumString.toInt() the code breaks. It will compile, but when I try to run an emulator it casts error codes about the toInt declaration. The code is using toInt in this because I was trying to see if the emulator would like that. Also whenever I declare that toInt it highlights in a light yellow italic font, which I haven't seen before.
I have Edited your code.
Changes to the code is explained with the comments below.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
val tenPerTip: Button = findViewById(R.id.tenPerTipButton)
val fifteenPerTip: Button = findViewById(R.id.fifteenPerTipButton)
val twentyPerTip: Button = findViewById(R.id.twentyPerTipButton)
val customTip: Button = findViewById(R.id.customTipSubmit)
val sumRaw: EditText = findViewById(R.id.billEnter)
val tipOnlyResult: TextView = findViewById(R.id.tipOnlyResult)
val totalResult: TextView = findViewById(R.id.totalResult)
/** if you put sumString and sumInput here, what happens is when your app
* is created and the onCreate method is called sumString is initialized
* here without using .text, i.e., sumRaw.text command what happens is sumString
* will be initialized with sumRaw value (i guess maybe sumRaw id) and you will
* get error.
* Also, this is only called once when all the other variable are initialized.
* If you want to use it outside use a TextWatcher and change the variable as
* soon as it is updated in the EditText.
* A work-around would be initializing this value inside OnClickListener, what
* happens here is whenever you click tenPerTip Button sumString is Initialized
* with current values in sumRaw EditText.
*
* Do use .text else it will give errors.
*/
tenPerTip.setOnClickListener {
val sumString = sumRaw.text.toString()
// what happens here is sumString is converted to Double if it has valid pattern
// else it will return null
// And then the elvis operator will check for null. If its null, it will not
// not proceed further and will get out the listener.
val sumInput = sumString.toDoubleOrNull() ?: return#setOnClickListener
val sumTotal = sumInput * 1.1
val tipOnly = sumInput * 0.1
tipOnlyResult.text = tipOnly.toString()
totalResult.text = sumTotal.toString()
}
fifteenPerTip.setOnClickListener {
}
twentyPerTip.setOnClickListener {
}
customTip.setOnClickListener {
}
}
}
You seem to think the that when you write val sumString = sumRaw.toString(), it gives you the text entered in R.id.billEnter which is not correct. to get text from an EditText you have to use text property. As for your code it can be fixed as
tenPerTip.setOnClickListener{
val sumString = sumRaw.text.toString()
val sumInput = sumString.toInt()
val sumTotal = sumInput * 1.1
val tipOnly = sumInput * 0.1
tipOnlyResult.text = tipOnly.toString()
totalResult.text = sumTotal.toString()
}
Related
This is an application with a list of dogs and information about the dog.
I'm trying to run a DetailActivity that contains information about a dog. It is launched after clicking the Show Details button, which has a setOnClickListener and runs the Intent, passing the name, age, hobby and other parameters of the dog to the running DetailActivity. But when I try to take those parameters in the DetailActivity code, they all equal null.
It's actually very simple and I've done the same thing in google course codelab before (now I decided to practice a bit) and I repeat everything as it's written there, but I don't understand what I'm doing wrong.
I'll insert the DetailActivity and DogCardAdapter code below. You can also see all the code at this link on GitHub: https://github.com/theMagusDev/DogglersApp
DetailActivity.kt:
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.dogglers.databinding.ActivityDetailBinding
class DetailActivity() : AppCompatActivity() {
private lateinit var binding: ActivityDetailBinding
private val TAG = "DetailActivity"
companion object {
const val DOG_IMAGE = "dogImage"
const val DOG_NAME = "dogName"
const val DOG_AGE = "dogAge"
const val DOG_HOBBIES = "dogHobbies"
const val DOG_SEX = "dogSex"
}
val dogImageResourceId = intent?.extras?.getString(DOG_IMAGE)
val dogName = intent?.extras?.getString(DOG_NAME)
val dogAge = intent?.extras?.getString(DOG_AGE)
val dogHobbies = intent?.extras?.getString(DOG_HOBBIES)
val dogSex = intent?.extras?.getString(DOG_SEX)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Setup view binding
binding = ActivityDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
val heOrShe: String = when(dogSex){
"male" -> "He"
else -> "She"
}
binding.dogName.text = dogName
Log.d(TAG, "${dogAge.toString()}, ${dogName.toString()}, $dogHobbies, $heOrShe, $dogImageResourceId")
binding.dogDescription.text = getString(R.string.dog_description, dogName, dogAge, dogSex, dogHobbies)
//binding.dogImage.setImageResource(dogImageResourceId!!.toInt())
binding.dogImage.setImageResource(R.drawable.bella)
Log.d(TAG, "dogDescription and dogImage were set")
title = getString(R.string.details_about, dogName)
}
Logcat:
2022-10-02 08:32:25.545 9660-9660/com.example.dogglers D/DetailActivity: null, null, null, She, null
2022-10-02 08:32:25.558 9660-9660/com.example.dogglers D/DetailActivity: dogDescription and dogImage were set
DogCardAdapter.kt:
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.dogglers.DetailActivity
import com.example.dogglers.DetailActivity.Companion.DOG_AGE
import com.example.dogglers.DetailActivity.Companion.DOG_HOBBIES
import com.example.dogglers.DetailActivity.Companion.DOG_IMAGE
import com.example.dogglers.DetailActivity.Companion.DOG_NAME
import com.example.dogglers.DetailActivity.Companion.DOG_SEX
import com.example.dogglers.R
import com.example.dogglers.const.Layout.GRID
import com.example.dogglers.data.DataSource
/**
* Adapter to inflate the appropriate list item layout and populate the view with information
* from the appropriate data source
*/
class DogCardAdapter(
private val context: Context?,
private val layout: Int
): RecyclerView.Adapter<DogCardAdapter.DogCardViewHolder>() {
// Initialize the data using the List found in data/DataSource
val data = DataSource.dogs
/**
* Initialize view elements
*/
class DogCardViewHolder(view: View?): RecyclerView.ViewHolder(view!!) {
// Declare and initialize all of the list item UI components
val imageView: ImageView = view!!.findViewById(R.id.dog_image)
val dogName: TextView = view!!.findViewById(R.id.dog_name)
val dogAge: TextView = view!!.findViewById(R.id.dog_age)
val dogHobbies: TextView = view!!.findViewById(R.id.dog_hobbies)
var dogSex = "n/a"
val showDetailsButton: Button = view!!.findViewById(R.id.details_button)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DogCardViewHolder {
// Use a conditional to determine the layout type and set it accordingly.
// if the layout variable is Layout.GRID the grid list item should be used. Otherwise the
// the vertical/horizontal list item should be used.
val layoutType = when(layout) {
GRID -> R.layout.grid_list_item
else -> R.layout.vertical_horizontal_list_item
}
// Inflate the layout
val adapterLayout =LayoutInflater.from(parent.context)
.inflate(layoutType, parent, false)
// Null should not be passed into the view holder. This should be updated to reflect
// the inflated layout.
return DogCardViewHolder(adapterLayout)
}
override fun getItemCount(): Int = data.size
override fun onBindViewHolder(holder: DogCardViewHolder, position: Int) {
val resources = context?.resources
// Get the data at the current position
val item = data[position]
// Set the image resource for the current dog
holder.imageView.setImageResource(item.imageResourceId)
// Set the text for the current dog's name
holder.dogName.text = item.name
// Set the text for the current dog's age
holder.dogAge.text = resources?.getString(R.string.dog_age, item.age)
// Set the text for the current dog's hobbies by passing the hobbies to the
// R.string.dog_hobbies string constant.
holder.dogHobbies.text = resources?.getString(R.string.dog_hobbies, item.hobbies)
// Passing an argument to the string resource looks like:
// resources?.getString(R.string.dog_hobbies, dog.hobbies)
// Set the dog's sex variable
holder.dogSex = item.sex
// Declare context var
val context = holder.itemView.context
// Setting up OnClickListener
holder.showDetailsButton.setOnClickListener {
val intent = Intent(context, DetailActivity::class.java)
intent.putExtra(DOG_IMAGE, item.imageResourceId.toInt())
intent.putExtra(DOG_NAME, holder.dogName.toString())
intent.putExtra(DOG_AGE, holder.dogAge.toString())
intent.putExtra(DOG_HOBBIES, holder.dogHobbies.toString())
intent.putExtra(DOG_SEX, holder.dogSex.toString())
context.startActivity(intent)
}
}
}
I am getting some kind of empty string Amount function but dont know as im passing not null and non empty string
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText: EditText = findViewById(R.id.cost_of_service)
val radioGroup: RadioGroup = findViewById(R.id.tip_options)
val cal: Button = findViewById(R.id.calculate_button)
val message: String = editText.text.toString()
val tv: TextView = findViewById(R.id.tip_result)
getSignal(radioGroup, cal, message, tv)
}
private fun getSignal(radioGroup: RadioGroup, cal: Button, message: String, tv: TextView){
cal.setOnClickListener{
val selectedRB: RadioButton = findViewById(radioGroup!!.checkedRadioButtonId) //selectedRB -> selected radio button id
val per: String = selectedRB.text.toString()
val amount: Double = Amount(per, message)
tv.text = amount.toString()
}
}
private fun Amount(per: String, message: String): Double {
return message.toDouble() + (message.toInt() * per.toInt()) / 100
}
val message: String = editText.text.toString()
That gets the value of the editText at the time its called. It does not update it as it changes. Since you're calling this in onCreate, its almost certainly empty. And since it's empty, its not a numbver so trying to convert it to one fails.
The fix for this is to put this inside your onClickListener. Do the same for every field you want to get the text out of.
My app has 2 screens and works correctly in development so far. It already has 2 buttons ('toss' and 'startGame'which work correctly. Now I have added a further button called 'balls', designed to change the background colours of 4 TextViews ('ball1' to 'ball4'). However, pressing it once does nothing, and pressing it again causes the app to stop, with the displayed message "GC Clicker has stopped" or "GC Clicker keeps stopping".
Here is the first section of my MainActivity.kt:
package com.example.golfclicker
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.EditText
import android.widget.TextView
import android.graphics.Color
import android.widget.Button
import android.content.Intent
import android.media.AudioManager
import android.media.SoundPool
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val soundPool:SoundPool?
// Link variables to xml views
val player1Name = findViewById<EditText>(R.id.PersonName1)
val handicap1 = findViewById<EditText>(R.id.hpInput1)
val player2Name = findViewById<EditText>(R.id.PersonName2)
val handicap2 = findViewById<EditText>(R.id.hpInput2)
val startGame = findViewById<Button>(R.id.startGame)
val toss = findViewById<Button>(R.id.toss)
val bkgnd1 = findViewById<TextView>(R.id.Background1)
val bkgnd1a = findViewById<TextView>(R.id.Background1a)
val bkgnd1b = findViewById<TextView>(R.id.Background1b)
val bkgnd2 = findViewById<TextView>(R.id.Background2)
val bkgnd2a = findViewById<TextView>(R.id.Background2a)
val bkgnd2b = findViewById<TextView>(R.id.Background2b)
val balls = findViewById<Button>(R.id.balls)
val ball1 = findViewById<TextView>(R.id.ball1)
val ball2 = findViewById<TextView>(R.id.ball2)
val ball3 = findViewById<TextView>(R.id.ball3)
val ball4 = findViewById<TextView>(R.id.ball4)
var priSec = true // True:Primaries False:Secondaries
var tossedP1 = "" //String values to pass to Intent
var tossedHp1 =""
var tossedP2 = ""
var tossedHp2 =""
var tossed = false //has Toss button been used?
//Set up soundpool and load the sound file
soundPool = SoundPool(2,AudioManager.STREAM_MUSIC,0)
val sound1 = soundPool.load(baseContext,R.raw.computer_keyboard,1)
val sound2 = soundPool.load(baseContext,R.raw.coins,1)
//Handle balls button click
balls.setOnClickListener {
if(priSec==true) {
with(ball1) { setBackgroundColor(Color.parseColor("button_blue")) }
with(ball2) { setBackgroundColor(Color.parseColor("red")) }
with(ball3) { setBackgroundColor(Color.parseColor("black")) }
with(ball4) { setBackgroundColor(Color.parseColor("yellow")) }
} else {
with(ball1) { setBackgroundColor(Color.parseColor("green")) }
with(ball2) {setBackgroundColor(Color.parseColor("pink")) }
with(ball3) {setBackgroundColor(Color.parseColor("brown")) }
with(ball4) {setBackgroundColor(Color.parseColor("white")) }
}
priSec = !priSec //toggle primary/secondary
}
//Handle 'Toss' button click
toss.setOnClickListener {
var ran = (0..1).random() //Toss coin
// val ran = 1 //checking name-swapping
Any suggestions would be welcome.
Color.parseColor(...) works in different way than you think.
You can parse color like this:
Color.parseColor("#ff77bb")
In other words, you must pass hex code of color
this line is wrong .. because you didn't define the color
setBackgroundColor(Color.parseColor("button_blue")
try
setBackgroundColor(Color.parseColor("#39b8db")
or
context.getResources().getColor(android.R.color.white)
I finally found the following works to use colours defined in colors.xml.
I didn't want to include hex colours in my main code, as I may want to edit them at a later date.
ball1.setBackgroundColor(getResources().getColor(R.color.button_blue))
Thanks Niaj; this is similar to your last suggestion.
So I'm trying to learn Kotlin and i'm a few days in. I am trying to build a Coin Calculator app that will take input of quantity of each type of coin you have and then using a class value it will add up all your change and tell you a total. I apologize for not being able to be too specific other than my error: None of the following functions can be called with the arguments supplied:
public final operator fun times(other: Byte): Double defined in kotlin.Double
public final operator fun times(other: Double): Double defined in kotlin.Double
it's showing these on my quarter total and dime total variables.
As I said I am new and actively studying looking for insight on what I am doing wrong, also any other advice over my messy coding that you see would be greatly appreciated.
-Thanks!
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//MyCode
val submitButton: Button = findViewById(R.id.submit)
var quarterQuan: EditText = findViewById(R.id.quarterInput)
var dimeQuan: EditText = findViewById(R.id.dimeInput)
submitButton.setOnClickListener{
val dime = Dime()
val quarter= Quarter()
var quarterTotal: Float = quarter.quarterVal*quarterQuan
var dimeTotal: Float = dime.dimeVal*dimeQuan
var cashTotal: Float = dimeTotal + quarterTotal
val resultTextViewLabel: TextView = findViewById(R.id.textResult)
resultTextViewLabel.text = cashTotal.toString()
}
}
}
class Quarter(){
val quarterVal = 0.25
}
class Dime(){
val dimeVal = 0.10
}
quarterQuan and dimeQuan are of type EditText (they are not numbers) and cannot be multiplied with a Float.
What you need to do is to read the values of these EditTexts:
val quarterEditTextValue = quarterQuan.text.toString().toFloat()
val dimeEditTextValue = dimeQuan.text.toString().toFloat()
You can then use these values for multiplication
var quarterTotal = quarter.quarterVal*quarterEditTextValue
var dimeTotal = dime.dimeVal*dimeEditTextValue
Have to add that you need to make each initial EditText value to be 0.0 to avoid NumberFormatException.
<EditText
android:id="#+id/quarterInput"
android:text="0.0" .... />
I try to change a public variable in kotlin but i can't. When I receive the variable in another script, it has not changed. I print the variable in the second script but then it says zero. I have no idea why. Please help me. I'm stuck. Here are my code:
package com.backal.bingolooooooooooooto
import android.content.Intent
import android.os.Bundle
import android.util.Log.d
import android.view.View
import androidx.appcompat.app.AppCompatActivity
class AddFavourActivity: AppCompatActivity() {
public var clicked = 0;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.add_favour)
val alt1: View = findViewById(R.id.alt1)
val alt2: View = findViewById(R.id.alt2)
val alt3: View = findViewById(R.id.alt3)
val alt4: View = findViewById(R.id.alt4)
val alt5: View = findViewById(R.id.alt5)
val alt6: View = findViewById(R.id.alt6)
val alt7: View = findViewById(R.id.alt7)
alt1.setOnClickListener {
var clicked = 50
startActivity(Intent(this, EnterPasswordActivity::class.java))
}
alt2.setOnClickListener {
var clicked = 80
d("Alexander", "Clicked is: $clicked")
startActivity(Intent(this, EnterPasswordActivity::class.java))
}
alt3.setOnClickListener {
startActivity(Intent(this, EnterPasswordActivity::class.java))
clicked = 100
}
alt4.setOnClickListener {
startActivity(Intent(this, EnterPasswordActivity::class.java))
clicked = 300
}
alt5.setOnClickListener {
startActivity(Intent(this, EnterPasswordActivity::class.java))
clicked = 500
}
alt6.setOnClickListener {
startActivity(Intent(this, EnterPasswordActivity::class.java))
clicked = 100
}
alt7.setOnClickListener {
startActivity(Intent(this, EnterPasswordActivity::class.java))
clicked = 1000
}
}
}
every time you are doing var clicked = 50 you're declaring a new variable (even if it's the same name) so just remove the var :
clicked = 50
something else you might want to consider is to rather make use of a companion object :
companion object {
var clicked = 0
}
then you can use this variable everywhere, by just using: AddFavourActivity.clicked
or AddFavourActivity.clicked = 50
A companion object will ensure the same instance of the variable is used everywhere
You keep creating a new variable called clicked when you do:
var clicked = 80
You should simply do:
clicked = 80
Notice I removed the var as if you don't it simply creates a new variable withing the scope of the block called clicked and it doesn't modify the global clicked variable that you created.