My TextView shows empty when the application starts - android

I'm new at Kotlin, and I'm doing a simple app where the user writes something on EditText, presses a button then the app proceeds to show that text on SecondActivity, on that SecondActivity the user can do exactly the same thing, but on the FirstActivity (the one who shows up on the user starts the app) there are on EditText with "Welcome" text for default that shows empty when the application starts, this started to happen when I implement the text to be substituted by what the user writes on the SecondActivity
Here's the code for the FirtActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val result = findViewById<TextView>(R.id.nomeUser)
val nameEntered = findViewById<EditText>(R.id.nameEntered)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener{
val name = nameEntered.text.toString()
val intent = Intent(this#MainActivity, NomeEscrito::class.java)
intent.putExtra("Name", name)
startActivity(intent)
}
val intent = intent
val name = intent.getStringExtra("Name")
result.text = name
}
}
And here's the code for the SecondActivity
class NomeEscrito : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_nome_escrito)
val intent = intent
val name = intent.getStringExtra("Name")
val result = findViewById<TextView>(R.id.result)
result.text = name
val wordEntered = findViewById<EditText>(R.id.textPhrase)
val button2 = findViewById<Button>(R.id.button2)
button2.setOnClickListener{
val name2 = wordEntered.text.toString()
val intent2 = Intent(this#NomeEscrito, MainActivity::class.java)
intent2.putExtra("Name", name2)
startActivity(intent2)
}
}
}

The problem is in the following line of your FirstActivity:
val name = intent.getStringExtra("Name")
When you open up the app for the first time, there is no data in the intent. As a result, it returns an empty string.
You can do the a check for empty string before setting your EditText text to avoid this situation:
if (!name.isNullOrBlank()) {
result.text = name
}

Choose different keys in getStringExtra in both intent data passing

Related

how to save data from textview when going to previous activity kotlin

So I have a child activity that I press two buttons, one to increment and one to decrement. I want to save this number when I go back to the previous activity. However, I am stuck here. I tried using shared preference, however that seems to work for main to secondary activity. I tried using Activity Result and that seems way above me right now. I want my value in the textView to stay until I press a button to reset the whole thing.
This is the parent activity.
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
class TallBoys : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tall_boys)
val btn1: Button = findViewById(R.id.button1)
val btn2: Button = findViewById(R.id.button2)
val btn3: Button = findViewById(R.id.button3)
val btn4: Button = findViewById(R.id.button4)
val btn5: Button = findViewById(R.id.button5)
val btn6: Button = findViewById(R.id.button6)
val btn7: Button = findViewById(R.id.button7)
btn1.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
}
btn2.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
btn3.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
btn4.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
btn5.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
btn6.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
btn7.setOnClickListener {
val intent = Intent(this, TallBoysNumbers::class.java)
startActivity(intent)
}
}
}
This is the child activity
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class TallBoysNumbers : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tall_boys_numbers)
val confirmBtn: Button = findViewById(R.id.confirm_button)
val plusBtn: Button = findViewById(R.id.plus)
val textView = findViewById<TextView>(R.id.numbers)
val negBtn: Button = findViewById(R.id.negative)
var count = 0
plusBtn.setOnClickListener {
count++
textView.text = count.toString()
if (count >= 8) {
plusBtn.isEnabled = false
negBtn.isEnabled = true
}
}
negBtn.setOnClickListener {
count--
textView.text = count.toString()
if (count <= 0) {
negBtn.isEnabled = false
plusBtn.isEnabled = true
}
}
confirmBtn.setOnClickListener {
finish()
}
}
}
There are a lot of ways to do this, so I'm just going to show how to do it using SharedPreferences. The steps you need are:
In the parent activity, load the saved numbers from SharedPreferences in onResume and set the views accordingly. This needs to be in onResume so that it is also called when returning from the child activity after the numbers are modified.
Pass the key that is being edited to the child activity, so that it can save it in the correct spot in the SharedPreferences. The child activity can also use this key to load the current value so it is initialized correctly.
For example, in the parent activity
class ShowNumbersActivity : AppCompatActivity() {
private lateinit var prefs: SharedPreferences
private lateinit var txt1: TextView
private lateinit var txt2: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_show_numbers)
prefs = getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE)
val btn1 = findViewById<Button>(R.id.btn1)
val btn2 = findViewById<Button>(R.id.btn2)
txt1 = findViewById(R.id.txt1)
txt2 = findViewById(R.id.txt2)
// When you click on "Button 1" you have to signal
// to the second activity which key you are editing
btn1.setOnClickListener {
val i = Intent(this, PickNumber::class.java)
i.putExtra("KEY","VAL1")
startActivity(i)
}
btn2.setOnClickListener {
val i = Intent(this, PickNumber::class.java)
i.putExtra("KEY","VAL2")
startActivity(i)
}
}
// Update the displayed state in onResume
// so that it is updated after returning from the
// child activity editing the number
override fun onResume() {
super.onResume()
val num1 = prefs.getInt("VAL1", 0)
val num2 = prefs.getInt("VAL2", 0)
txt1.text = num1.toString()
txt2.text = num2.toString()
}
}
Then in the child activity, get the "KEY" and the same SharedPreferences instance and edit it when you click "Submit"
class PickNumber : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pick_number)
val key = intent.getStringExtra("KEY")
if( key == null ) {
finish()
}
val prefs = getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE)
val txt = findViewById<EditText>(R.id.num)
val submit = findViewById<Button>(R.id.submit)
// load the current value and display it
val current = prefs.getInt(key, 0)
txt.setText(current.toString())
submit.setOnClickListener {
// Get the updated number, save it to shared preferences
// (remember to call "apply") and finish this activity.
// When onResume is called in the parent activity it will
// load this updated number.
val num = txt.text.toString()
val numI = num.toIntOrNull() ?: 0
prefs.edit().putInt(key, numI).apply()
finish()
}
}
}
If you want to clear the numbers, you could make a button that calls prefs.edit().clear().apply() to erase all the saved values, or prefs.edit().remove(someKey).apply() to erase just one specific value.
There are definitely better ways to do this - if you switch to using a Fragment like you indicated these could be stored in a shared ViewModel that handles persistence and would be a cleaner design overall.
You are calling "finish" method. This will finish TallBoysNumbers activity without saving any data. Do not use SharedPreferences for that. What you'll need is "startActivityForResult".
This will allow you to save the data before calling "finish" AND getting it from the caller activity. Take a look here:
https://developer.android.com/training/basics/intents/result
with using shared pref I hope it will come to you
class dataShared() for saving count
class DataShared(
context: Context,
userSharedPrefName:String="USER_SHARED_PREF_NAME"
) {
private val sharedPreferences: SharedPreferences =
context.getSharedPreferences(
userSharedPrefName, Context.MODE_PRIVATE
)
fun getCount(): Int {
return (sharedPreferences.getInt("count", 0))
}
fun setCount(value: Int) {
val editor = sharedPreferences.edit()
editor.putInt("count", value)
editor.apply()
}
}
plusBtn and negBtn
val data=DataShared(this)
plusBtn.setOnClickListener {
if (data.getCount()<7) {
data.setCount(data.getCount() + 1)
textView.text = data.getCount().toString()
}
}
negBtn.setOnClickListener {
if (data.getCount()>=1){
data.setCount(data.getCount()-1)
textView.text=data.getCount().toString()
}
}

Start another activity error message for editText

https://developer.android.com/training/basics/firstapp/starting-activity#kotlin
I am at this point on the training and have added the code as advised:
const val EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
/** Called when the user taps the Send button */
fun sendMessage(view: View) {
val editText = findViewById<EditText>(R.id.editText)
val message = editText.text.toString()
val intent = Intent(this, DisplayMessageActivity::class.java).apply {
putExtra(EXTRA_MESSAGE, message)
}
startActivity(intent)
}
}
However it doesn't like editText in (R.id.editText). It is showing in red and pressing alt + enter has not worked on this. I am only expecting to see an error on DisplayMessageActivity.
I have tried to find a fix to this error online but I can't seem to find anything to help.
Thank you all, this has now been resolved.
User Jems asked me to check the activity_main.xml to see if I had an id of editText. I did but it had additional wording. It was showing as editTextTextName, so I amended this to show only editText and now it is happy with the code.
Try With This:
val editText = findViewById<EditText>(R.id.editText) as EditText
Update
const val EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText = findViewById<EditText>(R.id.editText) as EditText
val message = editText.text.toString()
}
/** Called when the user taps the Send button */
fun sendMessage(view: View) {
val intent = Intent(this, DisplayMessageActivity::class.java).apply {
putExtra(EXTRA_MESSAGE, message)
}
startActivity(intent)
}
}

Adding data of a data class to a mutablelist that is a parameter of another data class Kotlin Androidx

My addMeal function expects a restaurant/YelpRestaurant (that was previously selected by the user.. see images)
How do I pass that selected restaurant in?? Hope this is very simple and I am overthinking it
This is my first kotlin android project so apologies for stupidity.
User selects a restaurant
User decides to add a thought for that particular restaurant
User clicks button and thought/UserMeal is added to the "meals" arraylist of the selected restaurant
Data classes____
data class YelpSearchResult(
#SerializedName ("total") val total: Int,
#SerializedName ("businesses") val restaurants: List<YelpRestaurant>
)
data class YelpRestaurant(
val name: String,
val rating: Double,
val price: String,
#SerializedName("review_count") val numReviews: Int,
#SerializedName("image_url") val imageUrl: String,
val categories: List<YelpCategory>,
val location: YelpLocation,
val meals: MutableList<UserMeals> = ArrayList()
)
data class UserMeals (
val mealName: String,
val mealPrice: Double,
val mealThoughts: String
)
I'm only interested in the meals list and the UserMeals data class
class ThoughtsActivity : AppCompatActivity() {
lateinit var mealName : String
lateinit var mealPrice : String
lateinit var mealThought : String
lateinit var addedMeal : UserMeals
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_thoughts)
thoughtBtn.setOnClickListener() {
mealName = m_name.text.toString()
mealPrice = m_price.text.toString()
mealThought = m_thought.text.toString()
val addedMeal = UserMeals(mealName,mealPrice.toDouble(),mealThought)
if(mealName.isNotEmpty()){
addMeal()
}
val intent = Intent(this, RestaurantActivity::class.java)
intent.putExtra("MEALNAME", mealName)
intent.putExtra("PRICE", mealPrice)
intent.putExtra("MEALTHOUGHT", mealThought)
}
}
fun addMeal(restaurant: YelpRestaurant){
restaurant.meals.add(addedMeal)
}
-----EDIT-----
----My Activity for the middle screen where restaurant is passed in----
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_restaurant)
val button = findViewById<Button>(R.id.addBtn)
// rvThoughts.adapter = adapter
// rvThoughts.layoutManager = LinearLayoutManager(this)
button.setOnClickListener{
val intent = Intent(this, ThoughtsActivity::class.java)
intent.putExtra("restaurantObject", <??>)
startActivity(intent)
}
var intent = intent
val aName = intent.getStringExtra("iName")
val aRating = intent.getDoubleExtra("iRating",0.0)
val aPrice = intent.getStringExtra("iPrice")
val aReviews = intent.getStringExtra("iReviews")
val aImageUrl = intent.getStringExtra("iImageUrl")
val aCategory = intent.getStringExtra("iCategory")
val aLocation = intent.getStringExtra("iLocation")
r_name.text = aName
r_reviews.text = aReviews
r_rating.rating = aRating.toFloat()
r_price.text = aPrice
r_reviews.text = aReviews.toString()
Glide.with(applicationContext).load(aImageUrl).into(r_image)
r_category.text = aCategory
r_address.text = aLocation
}
Ok I got clarification from your question,
** Update **
Add in your app level gradle:
apply plugin: 'kotlin-android-extensions'
Then in your YelpRestaurant or whatever object you want to pass via intent make them implement Parcelable and annotate Parcelize:
#Parcelize
data class YelpRestaurant(...) : Parcelable
From there you can easily pass data class objects between intents. passing them:
val intent: Intent = Intent(this, SecondActivity::class.java)
intent.putExtra("restaurant", YelpRestaurant("hey", "hello"));
startActivity(intent)
And then retrieving them:
val intent: Intent = getIntent()
var yelresTaurant : YelpRestaurant = intent.getParcelableExtra("restaurant")
This is just a sample with your YelpRestaurant (didn't consider it's objects) but you should know the next steps.
Well you do have the info at the middle activity right then when you tap "ADD THOUGHTS" button then on the listener you'd have created intent then put a key and value pair of the restaurant there, that will be used to get the restaurant in this activity (ThoughtActivity).
Implement Parcelable:
YelpRestaurant(...): Parcelable
in the middle activity (where you have one pic and restaurant info):
val intent = Intent(this, ThoughtsActivity::class.java)
intent.putExtra("restaurantObject", <your yelp restaurant object here>)
In onCreate of ThoughtsActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_thoughts)
restaurant = intent.getExtra("restaurantObject") as YelpRestaurant
}
Edit: After OP's edit
Well your architecture is not well optimized.
On the very first activity you should be having the restaurant object and if not you'd create it using these things (from intent) you send in raw string to middle activity
Instead of sending these raw strings create an object of Yelp Resuturant from these data in the Main(First) Activity
//First activity
val restaurants = mutableListOf(YelpRestaurant(iName, iRating, ...), ...)
//and instead put the selected restaurant object
//example: view is that restaurant's object in selection activity
view.onClickListener {
val intent = Intent(this#MainActivity, MiddleActivity::class.java)
val restaurantSelected = restaurants.first {
//get child of the view and get the restaurant's name, store as resName
it.name == resName
}
intent.putExtra("restaurant_object", restaurantSelected)
startActivity(intent)
}
Inside your middle activity instead of fetching all those string values only get restaurant object
//not these
// val aName = intent.getStringExtra("iName")
// val aRating = intent.getDoubleExtra("iRating",0.0)
// val aPrice = intent.getStringExtra("iPrice")
// val aReviews = intent.getStringExtra("iReviews")
// val aImageUrl = intent.getStringExtra("iImageUrl")
// val aCategory = intent.getStringExtra("iCategory")
// val aLocation = intent.getStringExtra("iLocation")
val restaurant = intent.getExtra("restaurant_object") as YelpRestaurant
//now send this object to next activity

Trying to show the product of two EditTexts as a TextView in another activity

I am having a ton of trouble passing the product of two EditTexts to a TextView in another activity. Here is my code for MainActivity.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button1: Button = findViewById(R.id.button1)
val editText1: EditText = findViewById(R.id.editText1)
val editText2: EditText = findViewById(R.id.editText2)
val firstNumber = editText1.toString().toInt()
val secondNumber = editText2.toString().toInt()
val product = firstNumber * secondNumber
button1.setOnClickListener{
val intent = Intent(this, Activity2::class.java)
intent.putExtra("RESULT_PRODUCT", product)
startActivity(intent)
}
}
}
Here is my code for Activity2:
class Activity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_2)
val product = intent.getIntExtra("RESULT_SUM", 0)
textView1.text = product.toString()
}
}
I am relatively new to Kotlin and Android Studio but this has caused crashes left and right.
First of all, You have to calculate the product inside OnClickListener to get correct result.
button1.setOnClickListener{
val firstNumber = editText1.text.toString().trim()
val secondNumber = editText2.text.toString().trim()
if(!(firstNumber.isEmpty() or secondNumber.isEmpty())) {
val product = firstNumber.toInt() * secondNumber.toInt()
val intent = Intent(this, Activity2::class.java)
intent.putExtra("RESULT_PRODUCT", product)
startActivity(intent)
} else {
//Show messages
}
}
And then you have to use the exact key RESULT_PRODUCT that you use in your activity to pass data through intent
val product = intent.getIntExtra("RESULT_PRODUCT", 0)
You are passing "RESULT_PRODUCT" from MainActivity but getting "RESULT_SUM" in your Activity2. You should use intent.getIntExtra("RESULT_PRODUCT", 0) in you second activity.

app closes without going to the second screen

This is the main activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var userInput:EditText = findViewById(R.id.usr_input) as EditText
var button:Button = findViewById(R.id.ent_btn) as Button
button.setOnClickListener {
var name = userInput.text
val intent = Intent(this#MainActivity, screenTwo::class.java)
intent.putExtra("name", name)
startActivity(intent)
}
}
}
This is second screen
class screenTwo : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_screen_two)
var userName:TextView = findViewById(R.id.user_name) as TextView
var editText:EditText = findViewById(R.id.usr_text) as EditText
var outText:TextView = findViewById(R.id.output) as TextView
var showButton:Button = findViewById(R.id.btn_show) as Button
var back:Button = findViewById(R.id.btn_back) as Button
var name = intent.getStringExtra("name")
userName.text = name
showButton.setOnClickListener {
var text:String = editText.text.toString()
outText.text = text
}
back.setOnClickListener {
var goback = Intent(this#screenTwo, MainActivity::class.java)
startActivity(goback)
}
}
}
When I click on the button(variable_name) in the main activity, the app closes. Is it the intent or something is wrong in the second screen???
intent is not defind in SecondActivity
In SecondActivity : get intent by getIntent()
class screenTwo : AppCompatActivity() {
var name = getIntent().getStringExtra("name")
Most common error in this configuration is that you forgot to declare your screenTwo in your AndroidManifest.xml, inside the "application" node (your MainActivity should already be defined there) :
<activity
android:name=".screenTwo"
android:theme="yourTheme"/>
If this is not it, an error log might help us help you.
Sorry , it was a minor error from my side..
I didn't convert the variable 'name' to 'String'
var name = userInput.text.toString() //correction
It's working now,
Thanks anyway...

Categories

Resources