Kotlin: Set variable in secondary activity conditional on OnClick in main activity - android

I have a main activity with four card views. I want each card view, when clicked, to go to a multiple choice quiz specific to that card. In my questions activity, I need to identify which of the card views was clicked in order to determine which set of questions should be called. I tried using boolean values in my main activity but am not able to reference them in my questions activity.
Main Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
c1.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_a", true);
startActivity(intent)
finish()
}
c2.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_b", true);
startActivity(intent)
finish()
}
c3.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_c", true);
startActivity(intent)
finish()
}
c4.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_d", true);
startActivity(intent)
finish()
}
}
}
The intent.putExtra("booleanA", true) in my main activity and if boolean statement and var booleanA = getIntent().getExtras()!!.getBoolean("booleanA") declaration in my secondary activity crash the app. If I remove intent.putExtra("booleanA", true) and var booleanA = getIntent().getExtras()!!.getBoolean("booleanA")and remove the if statement, leaving just mQuestionsList = Constants.getQuestions(), the app no longer crashes
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_questions.*
class QuestionsActivity : AppCompatActivity(), View.OnClickListener {
private var mCurrentPosition:Int = 1
private var mQuestionsList:ArrayList<Questions>? = null
private var mSelectedOptionPosition:Int = 0
private var mCorrectAnswers: Int = 0
var booleanA = getIntent().getExtras()!!.getBoolean("booleanA")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_questions)
if (booleanA){
mQuestionsList = Constants.getQuestions()
}
setQuestion()
radio_button1.setOnClickListener(this)
radio_button2.setOnClickListener(this)
radio_button3.setOnClickListener(this)
radio_button4.setOnClickListener(this)
}

You Should do like this
class QuestionsActivity : AppCompatActivity(), View.OnClickListener {
private var mCurrentPosition:Int = 1
private var mQuestionsList:ArrayList<Questions>? = null
private var mSelectedOptionPosition:Int = 0
private var mCorrectAnswers: Int = 0
//don't get the intent data here
var booleanA: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_questions)
//get the intent data here
booleanA = getIntent().getExtras()!!.getBoolean("booleanA")
if (booleanA){
mQuestionsList = Constants.getQuestions()
}
setQuestion()
radio_button1.setOnClickListener(this)
radio_button2.setOnClickListener(this)
radio_button3.setOnClickListener(this)
radio_button4.setOnClickListener(this)
}

Related

I am not able to validate my new activity

I created a new empty activity for my project but I am getting an error. The activity file as well as the layout file is shown in red color. I tried creating an intent object from MainActivity, in order to start this activity but received the following error
Classifier 'Details' does not have a companion object, and thus must
be initialized here
I've attached a screenshot of my android studio.
Code for new activity
package com.example.safetyapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class Details : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
}
}
package com.example.safetyapp
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.firebase.ui.auth.AuthUI
import com.google.firebase.auth.FirebaseAuth
class MainActivity : AppCompatActivity() {
final val AUTH_REQUEST_CODE = 7192
lateinit var firebaseAuth:FirebaseAuth
lateinit var listener: FirebaseAuth.AuthStateListener
lateinit var providers: List<AuthUI.IdpConfig>
override fun onStart(){
super.onStart()
firebaseAuth.addAuthStateListener(listener)
}
override fun onStop(){
super.onStop()
if(listener!=null){
firebaseAuth.removeAuthStateListener(listener)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button2 = findViewById<Button>(R.id.button2)
val defence = findViewById<Button>(R.id.Defence)
button2.setOnClickListener{
val myintent = Intent(this, Details::class.java)
}
init()
}
private fun init() {
providers = arrayListOf(AuthUI.IdpConfig.PhoneBuilder().build(),
AuthUI.IdpConfig.EmailBuilder().build())
firebaseAuth = FirebaseAuth.getInstance()
listener = object:FirebaseAuth.AuthStateListener{
override fun onAuthStateChanged(p0: FirebaseAuth) {
val user = p0.currentUser
if(user!= null){
// Do something
}
else{
startActivityForResult(AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.setLogo(R.drawable.logo)
.build(),AUTH_REQUEST_CODE)
}
}
}
}
}
You didn't import the Details class, add this line between your MainActivity class imports
import com.example.safetyapp.Details

How do I save previous activity when starting a new intent?

I have two activities. One is the homepage with a button to add a dynamic button and the second page is two edit texts. So you click the button on the homepage and go to the second page where you input two edit texts and youre sent back to the homepage where a dynamic button set to one of the edit text is created. I made an inflator that allows you to go back into the second activity through the button but it starts a new second activity so the previous inputted edit texts are gone. How do I get them to stay?
Main page:
package com.example.quest
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.widget.Button
import android.widget.LinearLayout
import androidx.preference.PreferenceManager
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : AppCompatActivity() {
private val questionActivityCode = 2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<FloatingActionButton>(R.id.btn2).setOnClickListener{
startActivityForResult(Intent(this#MainActivity, SecondActivity::class.java), questionActivityCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == questionActivityCode && resultCode == Activity.RESULT_OK) {
createNewButtonWithText(data?.getStringExtra("test") ?: "")
}
}
private fun createNewButtonWithText(text: String)
{
val newbutton = Button(this#MainActivity)
val layout = findViewById<LinearLayout>(R.id.mainlayout)
newbutton.text = text
newbutton.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
newbutton.width=1010
newbutton.height=300
newbutton.gravity = Gravity.CENTER
newbutton.translationX= 65F
newbutton.setTextColor(Color.parseColor("#FFFFFFFF"))
newbutton.setBackgroundColor(Color.parseColor("#250A43"))
layout.addView(newbutton)
val inflator = layoutInflater
val builder = AlertDialog.Builder(this)
val intent = Intent(this#MainActivity, SecondActivity::class.java)
newbutton.setOnClickListener{
val dialogLayout = inflator.inflate(R.layout.text, null)
with(builder) {
setTitle(newbutton.text)
setPositiveButton("Edit"){dialog, which ->
startActivity(intent)
}
setNegativeButton("Cancel"){dialog, which ->
Log.d("Main", "Negative button clicked")
}
setView(dialogLayout)
show()
}
}
}}
Second Activity:
package com.example.quest
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import com.google.android.material.floatingactionbutton.FloatingActionButton
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val question = findViewById<EditText>(R.id.question)
val answer = findViewById<EditText>(R.id.answer)
findViewById<FloatingActionButton>(R.id.btn3).setOnClickListener {
val questiontext = question.text.toString()
val answertext = answer.text.toString()
val sharedPre = PreferenceManager.getDefaultSharedPreferences(this#SecondActivity).edit()
sharedPre.putString("question", questiontext)
sharedPre.putString("answer", answertext)
sharedPre.apply()
val returnIntent = Intent()
returnIntent.putExtra("test", questiontext)
setResult(Activity.RESULT_OK, returnIntent)
finish()
}
}
}
If you look at the activity lifecycle after creating an activity and when moving from one activity to the next activity the activity is destroyed, and a new activity is created. An easy way to save this data could be to use shared preferences whereby you can store the data when the user inputs it in the second activity and before you inflate the second activity check if the sharedprefs data is not null and use the data to update the activity else just create a new activity.
Are you using MVVM architecture? You should probably store all your value in ViewModel and call these values between activities in ViewModel, as View (Actiity/Fragment) is only responsible for UI-related task.
Here is a simple example
SharedViewModel
class SharedViewModel : ViewModel() {
// ViewModel that holds data-related values
var question: String ?= null
var answer: Stirng ?= null
}
SecondActivity
class SecondActivity : AppCompatActivity() {
private val sharedViewModel: SharedViewModel by viewModels() <-- add your viewmodel here
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val question = findViewById<EditText>(R.id.question)
val answer = findViewById<EditText>(R.id.answer)
// Step 1 - Check viewmodel's value and assign it back to edittext
if(sharedViewModel.question != null) {
question.text = sharedViewModel.question
}
if(sharedViewModel.answer != null) {
answer.text = sharedViewModel.answer
}
// Step 2 - Assign your value into viewmodel
findViewById<FloatingActionButton>(R.id.btn3).setOnClickListener {
sharedViewModel.question = question.text.toString()
sharedViewModel.answer = answer.text.toString()
returnIntent.putExtra("test", questiontext)
setResult(Activity.RESULT_OK, returnIntent)
finish()
}
}
}
Additional
onActivityResult will be deprecated soon in API 30, it it better you can learn ActivityResultContract
Try to use databinding as it helps to reduce many of the boilerplate since you're using kotlin.
Try to adapt to MVVM architecture as it helps you a lot in developing Android app.

How do you save previous activity data in Kotlin so when you reopen it, the same data is still there?

I'm making a quiz app and so far I've made the code for creating a question and answer in one activity which then takes you back to the main activity where a button with the text set to the question is created. I want to have it so that you can click that button and go back into the previous activity where you previously inputted the question and answer specifically for that button and have all of that still there. How exactly would I be able to create something like this? I've only ever seen a Java video for one but never a Kotlin. Here's my code for context:
MainActivity:
package com.example.quest
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : AppCompatActivity() {
private val questionActivityCode = 2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<FloatingActionButton>(R.id.btn2).setOnClickListener{
startActivityForResult(Intent(this#MainActivity, SecondActivity::class.java), questionActivityCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == questionActivityCode && resultCode == Activity.RESULT_OK) {
createNewButtonWithText(data?.getStringExtra("test") ?: "")
}
}
private fun createNewButtonWithText(text: String)
{
val newbutton = Button(this#MainActivity)
val layout = findViewById<LinearLayout>(R.id.mainlayout)
newbutton.text = text
newbutton.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
newbutton.width=1010
newbutton.height=300
newbutton.gravity = Gravity.CENTER
newbutton.translationX= 65F
newbutton.setTextColor(Color.parseColor("#FFFFFFFF"))
newbutton.setBackgroundColor(Color.parseColor("#250A43"))
layout.addView(newbutton)
val inflator = layoutInflater
val dialogLayout = inflator.inflate(R.layout.text, null)
val builder = AlertDialog.Builder(this)
val intent = Intent(this#MainActivity, SecondActivity::class.java)
newbutton.setOnClickListener{
with(builder) {
setTitle(newbutton.text)
setPositiveButton("Edit"){dialog, which ->
startActivity(intent)
}
setNegativeButton("Cancel"){dialog, which ->
Log.d("Main", "Negative button clicked")
}
setView(dialogLayout)
show()
}
}
}}
SecondActivity:
package com.example.quest
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.EditText
import com.google.android.material.floatingactionbutton.FloatingActionButton
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val question = findViewById<EditText>(R.id.question)
findViewById<FloatingActionButton>(R.id.btn3).setOnClickListener{
val questiontext = question.text.toString()
val returnIntent = Intent()
returnIntent.putExtra("test", questiontext)
setResult(Activity.RESULT_OK, returnIntent)
finish()
}
}
}
you can use onSaveIntanceState method to save current activity data
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putString("activity", "my activity data");
// etc.
}
and for retrieve data when activity resumed you have to use savedInstanceState
in onRestoreInstanceState method or in onCreate method
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
String myString = savedInstanceState.getBoolean("activity");
}

Trying to use onSaveInstanceState and onRestoreSaveInstanceState in order to save my activity state but it does not work

I'm trying to make a quiz app so that when the user clicks the plus button it takes them to a page where they input the question and answer which they can then save and is taken back to the previous page where a new button with the text set to the question is created. I have all of this coded and working except for the part where I can save the question/answer activity state if the user wants to edit it. I've tried to use onSaveInstanceState and onRestoreSaveInstanceState but it didn't save the activity at all. Can someone see what I'm doing wrong? Here's my code:
Main Activity:
package com.example.quest
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : AppCompatActivity() {
private val questionActivityCode = 2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<FloatingActionButton>(R.id.btn2).setOnClickListener{
startActivityForResult(Intent(this#MainActivity, SecondActivity::class.java), questionActivityCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == questionActivityCode && resultCode == Activity.RESULT_OK) {
createNewButtonWithText(data?.getStringExtra("test") ?: "")
}
}
private fun createNewButtonWithText(text: String)
{
val newbutton = Button(this#MainActivity)
val layout = findViewById<LinearLayout>(R.id.mainlayout)
newbutton.text = text
newbutton.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
newbutton.width=1010
newbutton.height=300
newbutton.gravity = Gravity.CENTER
newbutton.translationX= 65F
newbutton.setTextColor(Color.parseColor("#FFFFFFFF"))
newbutton.setBackgroundColor(Color.parseColor("#250A43"))
layout.addView(newbutton)
val inflator = layoutInflater
val builder = AlertDialog.Builder(this)
val intent = Intent(this#MainActivity, SecondActivity::class.java)
newbutton.setOnClickListener{
val dialogLayout = inflator.inflate(R.layout.text, null)
with(builder) {
setTitle(newbutton.text)
setPositiveButton("Edit"){dialog, which ->
startActivity(intent)
}
setNegativeButton("Cancel"){dialog, which ->
Log.d("Main", "Negative button clicked")
}
setView(dialogLayout)
show()
}
}
}}
Second Activity:
package com.example.quest
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.EditText
import com.google.android.material.floatingactionbutton.FloatingActionButton
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val question = findViewById<EditText>(R.id.question)
findViewById<FloatingActionButton>(R.id.btn3).setOnClickListener{
val questiontext = question.text.toString()
val returnIntent = Intent()
returnIntent.putExtra("test", questiontext)
setResult(Activity.RESULT_OK, returnIntent)
finish()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
Log.i("Instance State", "onSaveInstanceState")
val question = findViewById<EditText>(R.id.question)
val answer = findViewById<EditText>(R.id.answer)
outState.putCharSequence("savedQuestion", question.toString())
outState.putCharSequence("savedAnswer", answer.toString())
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
Log.i("Restored Instance State", "onRestoreInstanceState")
val question = savedInstanceState.getCharSequence("savedQuestion")
val answer = savedInstanceState.getCharSequence("savedAnswer")
val txt = findViewById<EditText>(R.id.question)
val txt2 = findViewById<EditText>(R.id.answer)
txt.setText(question)
txt2.setText(answer)
}
}
That is not the use case for onSaveInstanceState and onRestoreInstanceState. You should use them when your Activity is recreated. For example: device is rotated.
In your case, you are starting a new instance of SecondActivity when you are starting it from MainActivity.
To achieve what you want, you should pass the question and answer from MainActivity to SecondActivity using a Bundle and then let the user edit them.

unable to display value from previous activity

While displaying value to a textview on second activity getting error as
expecting member declaration
This is my code for Another Activity:
package com.example.trial.sudoku_solver
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Bitmap
import android.media.MediaScannerConnection
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.text.Editable
import android.util.Log
import android.view.View
import android.widget.*
import com.example.trial.sudoku_solver.R
import kotlinx.android.synthetic.main.activity_main.view.*
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.*
import kotlinx.android.synthetic.main.activity_main.*
import org.w3c.dom.Text
class AnotherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_another)
}
var a: String = intent.getStringExtra("text")
val text1: TextView = findViewById(R.id.textview) as TextView
text1.text = intent.getStringExtra("text")
}
This is my partial code for the function in MainActivity
private fun clickText() {
val text1: EditText = findViewById(R.id.editText)
if (text1 != null) {
//Toast.makeText(this, text1.text, Toast.LENGTH_LONG).show()
var text1 = text1.editText.toString()
val intent = Intent(this, AnotherActivity::class.java)
intent.putExtra("text",text1)
startActivity(intent);
}
}
8You need to call intent, findViewById and then setText after the call to setContentView:
class AnotherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_another)
var a: String = intent.getStringExtra("text")
val text1: TextView = findViewById(R.id.textview) as TextView
text1.text = intent.getStringExtra("text")
}
}
The easiest way to do this :
Intent intent = new Intent(getBaseContext(), Activity2.class);
intent.putExtra("ID", sId);
startActivity(intent);
Access that intent on next activity
String sId= getIntent().getStringExtra("ID");
Hope this will help you
You need to add these piece of code inside onCreate method block
You should add your executable statements inside methods.
So the code will look like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_another)
// add these statement inside onCreate block
var a: String = intent.getStringExtra("text")
val text1: TextView = findViewById(R.id.textview) as TextView
text1.text = intent.getStringExtra("text")
}
Threre is no settext method in an Activity. You should set the text string to TextView like that:
var a: String = intent.getStringExtra("text")
val text1 = findViewById(R.id.textview) as TextView
text1.text = a
In addition, when you write code in kotlin, it is not necessary to use findViewById in activities. Because of synthetic properties, the views are accessible via their ids from xml file. So, your three line of code could be replaced as below:
textview.text = intent.getStringExtra("text")
Also change the code block in MainActivity to:
private fun clickText() {
val editText1: EditText = findViewById(R.id.editText)
if (editText1 != null) {
//Toast.makeText(this, text1.text, Toast.LENGTH_LONG).show()
var text1 = editText1.text.toString()
val intent = Intent(this, AnotherActivity::class.java)
intent.putExtra("text", text1)
startActivity(intent);
}
}

Categories

Resources