Trying to show two Toasts with some info, but one of them isn't showing up.
The points of interest in the code below are functions showScore() and checkAnswer(). The first one doesn't show up its Toast, the second one does. The project builds successfully and the app is working on my phone (Android 9, aarch64).
I just started learning Android. Maybe it's something stupid simple, but I can't get the reason why it's not working.
class MainActivity : AppCompatActivity() {
private lateinit var trueButton: Button
private lateinit var falseButton: Button
private lateinit var nextButton: ImageButton
private lateinit var prevButton: ImageButton
private lateinit var questionTextView: TextView
private val questionBank = listOf(
Question(R.string.question_australia, true),
Question(R.string.question_oceans, true),
Question(R.string.question_mideast, false),
Question(R.string.question_africa, false),
Question(R.string.question_americas, true),
Question(R.string.question_asia, true)
)
private val answers = mutableMapOf<Question, Boolean>()
private var currentIndex = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
trueButton = findViewById(R.id.true_button)
falseButton = findViewById(R.id.false_button)
nextButton = findViewById(R.id.next_button)
prevButton = findViewById(R.id.prev_button)
questionTextView = findViewById(R.id.question_text_view)
trueButton.setOnClickListener { view: View ->
checkAnswer(true)
}
falseButton.setOnClickListener { view: View ->
checkAnswer(false)
}
nextButton.setOnClickListener {
currentIndex = (currentIndex + 1) % questionBank.size
updateQuestion()
checkIfAnswered()
}
prevButton.setOnClickListener {
currentIndex = if (currentIndex > 0) (currentIndex - 1) else (questionBank.size - 1)
updateQuestion()
checkIfAnswered()
}
questionTextView.setOnClickListener {
currentIndex = (currentIndex + 1) % questionBank.size
updateQuestion()
checkIfAnswered()
}
updateQuestion()
}
private fun updateQuestion() {
val questionTextResId = questionBank[currentIndex].textResId
questionTextView.setText(questionTextResId)
}
private fun checkAnswer(userAnswer: Boolean) {
val question = questionBank[currentIndex]
val correctAnswer = question.answer
if (!answers.containsKey(question)) {
answers[question] = userAnswer
falseButton.isEnabled = false
trueButton.isEnabled = false
if (answers.size == questionBank.size) {
showScore()
}
} else {
return
}
val messageResId = if (userAnswer == correctAnswer) {
R.string.correct_toast
} else {
R.string.incorrect_toast
}
Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show()
}
private fun checkIfAnswered() {
if (answers.containsKey(questionBank[currentIndex])) {
falseButton.isEnabled = false
trueButton.isEnabled = false
} else {
falseButton.isEnabled = true
trueButton.isEnabled = true
}
}
private fun showScore() {
var score = 0
answers.forEach {
if (it.key.answer == it.value) {
score += 1
}
}
val toastText = "You answered $score of ${questionBank.size}"
Toast.makeText(this, toastText, Toast.LENGTH_SHORT).show()
}
}
UDP: Tried to run on my friend's phone (Android 9, aarch64) and faced the same issue.
Thanks to one Android-related chat, I found the problem. The problem is that one Toast appears on top of another one. Generally, it's a bad idea to use Toasts this way. If you have a similar problem, consider using Snackbar.
Related
I have a simple android app, which is changing text and color of TextView depends on how much passengers i added. I want to create a sealed class for each state.
Here is the code of the current app:
class MainActivity : AppCompatActivity() {
private var counter = 0
private val maxPassengers = 50
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.seats.text = counter.toString()
binding.minusButton.setOnClickListener {
counter -= 1
checkAndSwitchState(counter)
}
binding.plusButton.setOnClickListener {
counter += 1
checkAndSwitchState(counter)
}
binding.resetButton.setOnClickListener {
counter = 0
it.visibility = View.GONE
checkAndSwitchState(counter)
}
}
private fun checkAndSwitchState(counter: Int) {
if (counter == 0) {
binding.minusButton.isEnabled = false
binding.textView.text = binding.textView.context.getText(R.string.green_text)
binding.textView.setTextColor(Color.parseColor("#00FF00"))
binding.seats.text = counter.toString()
}
if (counter in 1 until maxPassengers) {
binding.minusButton.isEnabled = true
binding.textView.text = "Осталось мест: " + "${maxPassengers - counter}"
binding.textView.setTextColor(Color.parseColor("#0000FF"))
binding.seats.text = counter.toString()
}
if (counter >= maxPassengers) {
binding.resetButton.visibility = View.VISIBLE
binding.textView.text = binding.textView.context.getText(R.string.red_text)
binding.textView.setTextColor(Color.parseColor("#FF0000"))
binding.seats.text = counter.toString()
}
}
}
So the question is how can i use binding outside MainActivity in sealed class
I almost wrote a book application and I want to pass volume key events,
when user press a volume key goes to next page but I've got issue nextPage method is not running when up volume button is being pressed.
I used setonkeylistner in OnViewCreated but it's not working and I don't know any other way.
my project has only one activity(MainActivity) with many Fragments
sorry for my bad English
here is my Fragment code
class ShowPoemBodyFragment : Fragment(){
private val viewModel: PoemBodyViewModel by viewModels()
private var binding: FragmentShowPoemsBinding by autoCleared()
private var shared: SharedPreferences? = null
private var mId by Delegates.notNull<Int>()
private var fId by Delegates.notNull<Int>()
private var size by Delegates.notNull<Int>()
private var sharedBackground: SharedPreferences? = null
private var sharedImage: SharedPreferences? = null
private val poemAdapter = PoemBodyAdapter()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentShowPoemsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.root.setOnKeyListener(View.OnKeyListener { _, keyCode, _ ->
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
nextPage()
return#OnKeyListener true
} else
false
})
binding.poemBodyRecyclerView.adapter = poemAdapter
fId = requireArguments().getString("id")?.toIntOrNull()!!
size = requireArguments().getString("size")?.toIntOrNull()!!
viewModel.getPoemById(fId.toString())
Hawk.put("lastSeen", fId.toString())
Log.i("pomeid", fId.toString())
mId = fId
obserViewModel()
var fav: Int? = null
binding.markFavShowPoem.setOnClickListener {
if (fav == 1) {
fav = 0
binding.markFavShowPoem.setImageResource(R.drawable.ic_star)
} else {
fav = 1
binding.markFavShowPoem.setImageResource(R.drawable.ic_star_bold)
shared = context?.getSharedPreferences("shared_fav", Context.MODE_PRIVATE)
val editor: SharedPreferences.Editor = shared!!.edit()
editor.putString("id", mId.toString())
Toast.makeText(context, "به لیست علاقه مندی ها اضافه شد", Toast.LENGTH_SHORT).show()
editor.apply()
}
}
binding.textOption.setOnClickListener {
SubDialogFragmentPopUp().show(
requireActivity().supportFragmentManager,
"popUp"
)
}
if (mId == mId + size) {
binding.nextPage.visibility = View.INVISIBLE
} else
binding.nextPage.setOnClickListener {
nextPage()
}
if (mId == fId) {
binding.previousPage.visibility = View.INVISIBLE
}
else {
binding.previousPage.setOnClickListener{
mId -= 1
viewModel.getPoemById(mId.toString())
Hawk.put("lastSeen", mId.toString())
Log.i("pomeid", mId.toString())
obserViewModel()
}
}
//Set Background Text
sharedBackground =
context?.getSharedPreferences("shared_background_color", Context.MODE_PRIVATE)
val bbcg: Boolean = sharedBackground!!.getBoolean("bbcg", false)
if (bbcg) {
val color: Int = sharedBackground!!.getInt("background_color", 0)
view.background_show_poem_body.setBackgroundColor(color)
}
//Set Image
sharedImage = context?.getSharedPreferences("imagePoem", Context.MODE_PRIVATE)
val image: String? = sharedImage!!.getString("image", "")
context?.let {
Glide.with(this)
.load(image)
.centerCrop()
.error(R.drawable.ic_launcher_foreground)
.into(view.image_poem_adapter)
}
}
fun obserViewModel() {
viewModel.poemBody.observe(viewLifecycleOwner, Observer {
when (it.status) {
SUCCESS -> it.data?.let {
poemAdapter.updatePoems(it)
}
ERROR -> {
it.message?.let { requireActivity().toast(it) }
}
LOADING -> {
}
}
})
}
private fun nextPage(){
mId += 1
viewModel.getPoemById(mId.toString())
Hawk.put("lastSeen", mId.toString())
Log.i("pomeid", mId.toString())
obserViewModel()
}
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP){
// Do something
}
return super.onKeyUp(keyCode, event)
}
Try this and see
You need to use ACTION_MEDIA_BUTTON to listen for volume button presses. You will have to Override the key event. Here is a link that explains its use and why
I'd line to UI test a Custom Layout in a library module that doesn't have any Activities or Fragments. Is that even possible? All the information I can find about UI testing with Espresso needs an ActivityScenario or Fragment scenario, which I don't have in this case.
Here's the code of my Custom layout class, if that helps
class BuffView #JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: LinearLayout(context, attrs, defStyleAttr) {
private val buffView: LinearLayout = inflate(context, R.layout.buff_view, this) as LinearLayout
private var errorListener: ErrorListener? = null
private val apiErrorHandler = ApiErrorHandler()
private val getBuffUseCase = GetBuffUseCase(apiErrorHandler)
/**
* Handler for the time intervals between requests
*/
private val intervalsHandler = Handler()
private var countDownTimer: CountDownTimer? = null
private var buffIdCount = 1
/**
* Indicates whether the API request should be made or not
*/
private var getBuffs = false
fun init() {
getBuffs = true
getBuff()
}
private fun getBuff() {
if (!getBuffs) return
getBuffUseCase.invoke(Params(buffIdCount.toLong()), object : UseCaseResponse<Buff> {
override fun onSuccess(result: Buff) {
if (isDataValid(result)) displayBuff(result) else hideBuffView()
}
override fun onError(errorModel: ErrorModel?) {
errorListener?.onError(
errorModel?.message ?: context.getString(R.string.generic_error_message)
)
hideBuffView()
}
})
if (buffIdCount < NUM_BUFFS_TO_BE_FETCHED ) {
intervalsHandler.postDelayed({
buffIdCount++
getBuff()
stopCountDownTimer()
}, REQUEST_BUFF_INTERVAL_TIME)
}
}
private fun isDataValid(buff: Buff): Boolean {
if (buff.author.firstName.isNullOrEmpty() && buff.author.lastName.isNullOrEmpty()) {
showErrorInvalidData(context.getString(R.string.author_reason_error_message))
return false
}
if (buff.question == null || buff.question.title.isNullOrEmpty()) {
showErrorInvalidData(context.getString(R.string.question_reason_error_message))
return false
}
if (buff.timeToShow == null || buff.timeToShow < 0) {
showErrorInvalidData(context.getString(R.string.timer_reason_error_message))
return false
}
if (buff.answers == null || buff.answers.size < 2) {
showErrorInvalidData(context.getString(R.string.answers_reason_error_message))
return false
}
return true
}
private fun showErrorInvalidData(reason: String) {
errorListener?.onError(context.getString(R.string.data_incomplete_error_message, reason))
}
private fun displayBuff(buff: Buff) {
setBuffQuestion(buff.question!!.title!!)
setBuffAuthor(buff.author)
setBuffAnswers(buff.answers!!)
setBuffProgressBar(buff.timeToShow!!)
setBuffCloseButton()
invalidate()
showBuffView()
}
private fun setBuffQuestion(question: String) {
questionText.text = question
}
private fun setBuffAuthor(author: Buff.Author) {
val firstName = author.firstName ?: ""
val lastName = author.lastName ?: ""
val fullName = "$firstName $lastName"
authorName.text = fullName
author.image?.let { authorImageUrl ->
Glide.with(context)
.load(authorImageUrl)
.into(authorImage)
}
}
/**
* Adds a new answerView for each element in answers
* */
private fun setBuffAnswers(answers: List<Buff.Answer>) {
val answersContainer = findViewById<LinearLayout>(R.id.answersContainer)
answersContainer.removeAllViews()
for(answer in answers) {
val answerView: View = LayoutInflater.from(answersContainer.context).inflate(
R.layout.buff_answer,
answersContainer,
false
)
answer.answerImage?.x0?.url?.let {
Glide.with(context)
.load(it)
.into(answerView.answerImage)
}
answerView.setOnClickListener {
answerView.background = ContextCompat.getDrawable(
context,
R.drawable.answer_selected_bg
)
answerView.answerText.setTextColor(
ContextCompat.getColor(
context,
android.R.color.white
)
)
//freeze timer on answer selected
stopCountDownTimer()
//hide buff_content view 2 seconds after an answer has been selected
it.postDelayed({
hideBuffView()
}, HIDE_BUFF_AFTER_SELECTED_ANSWER_DURATION)
}
answerView.answerText?.text = answer.title
answersContainer.addView(answerView)
}
}
private fun setBuffProgressBar(timeToShow: Int) {
questionTimeProgress.max = timeToShow
countDownTimer = object : CountDownTimer(
timeToShow * ONE_SECOND_INTERVAL,
ONE_SECOND_INTERVAL
) {
override fun onTick(millisUntilFinished: Long) {
questionTimeText.text = (millisUntilFinished / ONE_SECOND_INTERVAL).toString()
questionTimeProgress.progress = timeToShow - (millisUntilFinished / ONE_SECOND_INTERVAL).toInt()
}
override fun onFinish() {
hideBuffView()
}
}.start()
}
private fun showBuffView() {
buffView.visibility = VISIBLE
val entryAnimation = AnimationUtils.loadAnimation(context, R.anim.entry_anim)
buffView.startAnimation(entryAnimation)
}
private fun hideBuffView() {
buffView.visibility = GONE
val exitAnimation = AnimationUtils.loadAnimation(context, R.anim.exit_anim)
buffView.startAnimation(exitAnimation)
}
private fun setBuffCloseButton() {
buffCloseImageButton.setOnClickListener {
hideBuffView()
stopCountDownTimer()
}
}
private fun stopCountDownTimer() {
countDownTimer?.cancel()
}
fun addErrorListener(errorListener: ErrorListener) {
this.errorListener = errorListener
}
}
The way I normally do it is to use another app module and put the UI tests there. For example, if app module depends of lib module, put the UI tests in app module.
But you could also create another separate "app lib testing" module (which would be an additional app type module), which would have the single responsibility of testing your library module.
I am not aware of more elegant solutions.
I'm basically making a simple calculator app using Kotlin. I'm very new to programming so I'm not familiar with Java either.
Basically the app runs and I'm also attaching a screenshot of the App's layout along with the code on MainActivity. Everything works fine except the clear button. Ideally, I want the clear button to reset the value on the 1st widget(results widget) and let me start a new calculation. Like how a AC button works on a regular calculator. However, all it does is clear the value. It doesn't clear the calculation. When I select the next calculation it still adds/subtracts/multiplies/divides to the previous value that's already there in the results widget. It doesn't let me start a new calculation like how I would be able to do if I pressed AC on a regular calculator.
Hope what i'm saying makes sense. Please tell me how can I make this work. And again, I'm very new to programming so would really really appreciate it if someone can help me.
package academy.learnprogramming.calculator
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
private const val TAG = "MainActivity"
private const val STATE_PENDING_OPERATION = "PendingOperation"
private const val STATE_OPERAND1 = "Operand1"
private const val STATE_OPERAND1_STORED = "Operand1_Stored"
class MainActivity : AppCompatActivity() {
private var operand1: Double? = null
private var operand2: Double = 0.0
private var pendingOperation = "="
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listener = View.OnClickListener { v ->
val b = v as Button
newNumber.append(b.text)
}
button0.setOnClickListener(listener)
button1.setOnClickListener(listener)
button2.setOnClickListener(listener)
button3.setOnClickListener(listener)
button4.setOnClickListener(listener)
button5.setOnClickListener(listener)
button6.setOnClickListener(listener)
button7.setOnClickListener(listener)
button8.setOnClickListener(listener)
button9.setOnClickListener(listener)
buttonDot.setOnClickListener(listener)
val opListener = View.OnClickListener { v ->
val op = (v as Button).text.toString()
try {
val value = newNumber.text.toString().toDouble()
performOperation(value, op)
} catch (e: NumberFormatException) {
newNumber.setText("")
}
pendingOperation = op
operation.text = pendingOperation
}
buttonEquals.setOnClickListener(opListener)
buttonDivide.setOnClickListener(opListener)
buttonMultiply.setOnClickListener(opListener)
buttonMinus.setOnClickListener(opListener)
buttonPlus.setOnClickListener(opListener)
buttonNegative.setOnClickListener { view ->
val value = newNumber.text.toString()
if (value.isEmpty()) {
newNumber.setText("-")
} else {
try {
var doubleValue = value.toDouble()
doubleValue *= -1
newNumber.setText(doubleValue.toString())
} catch (e: NumberFormatException) {
newNumber.setText("")
}
}
}
val value = newNumber.text.toString()
buttonClear.setOnClickListener { view ->
val value = 0
if (value == 0){
result.setText("")
}
}
}
private fun performOperation(value: Double, operation: String) {
if (operand1 == null) {
operand1 = value
} else {
operand2 = value
if (pendingOperation == "=") {
pendingOperation = operation
}
when (pendingOperation) {
"=" -> operand1 =
operand2
"/" -> if (operand2 == 0.0) {
operand1 = Double.NaN
} else {
operand1 =
operand1!! / operand2
}
"*" -> operand1 = operand1!! * operand2
"-" -> operand1 = operand1!! - operand2
"+" -> operand1 = operand1!! + operand2
}
}
result.setText(operand1.toString())
newNumber.setText("")
}
override fun onSaveInstanceState(outState: Bundle) {
Log.d(TAG, "onSaveInstanceState: Called")
super.onSaveInstanceState(outState)
if (operand1 != null) {
outState.putDouble(
STATE_OPERAND1,
operand1!!
)
outState.putBoolean(
STATE_OPERAND1_STORED,
true
)
}
outState.putString(STATE_PENDING_OPERATION, pendingOperation)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
if (savedInstanceState.getBoolean(
STATE_OPERAND1_STORED,
false
)
) {
operand1 = savedInstanceState.getDouble(STATE_OPERAND1)
} else {
operand1 = null
}
pendingOperation = savedInstanceState.getString(STATE_PENDING_OPERATION, "=")
operation.text = pendingOperation
}
}
Try resetting the values of operand1 and operand2
buttonClear.setOnClickListener { view ->
val value = 0
operand1 = null
operand2 = 0.0
if (value == 0){
result.setText("")
}
}
I have asked this similar questions multiple times and its been more than 2 weeks that I am trying to figure out a solution for it. Yes, I am aware that there are multiple similar question but the reason why I am asking is because none of the solutions from stack over flow work.I am a beginner in Android development, hence I ask you to kindly help me with this problem. I have almost given up on my project.
How app works
App has two activities. Main activity is used for showing data in form of card views using recycler view which is loaded from SQ Lite DB. User can click on a card which on clicking will launch a new activity(REFERENCE ACTIVITY). Data of clicked card is loaded in second activity. Here user can perform UPDATE or DELETE function.
PROBLEM
The problem is that I have to restart my app just to see a change in a note. For example, if I create a note in second activity and return to main activity, that CREATED note is NOT visible until app is restarted. Same goes for when a note is updated or deleted. Change only occurs when app is restarted.
What I have tried so far...
called notifyDataSetChanged() in onRestart() of MAIN activity.
Recalled whole load that loads recycler view items in first place in onRestart()
Tried updating adapter with the new data
----- CODES -----
MAIN ACTIVITY
class MainActivity : AppCompatActivity() {
var dbHandler: PediaDatabase = PediaDatabase(this)
var adapter: PediaAdapter? = null
var newAdapter: PediaAdapter? = null
var layoutManager: RecyclerView.LayoutManager? = null
var list: ArrayList<UserNotes>? = ArrayList()
var listItems: ArrayList<UserNotes>? = ArrayList()
var updatedList: ArrayList<UserNotes> = ArrayList()
var tempList: ArrayList<UserNotes>? = null
var myPrefs: SharedPreferences? = null
var first_run: Boolean = true
var isCreated: Boolean = false
var isUpdated: Boolean = false
var isDeleted: Boolean = false
var isReturning: Boolean = false
var updatedTitle: String? = null
var updatedText: String? = null
val PREFS_NAME: String = "MYPREFS"
val REQUEST_CODE: Int = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showOneTimeMessage()
invalidateOptionsMenu()
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
window.navigationBarColor = Color.BLACK
}
}
override fun onRestart() {
super.onRestart()
if(isUpdated)
{
recyclerViewID.recycledViewPool.clear()
var test = listItems!![adapPos]
test.noteTitle = updatedTitle
test.noteText = updatedText
listItems!!.set(adapPos, test)
adapter!!.notifyItemChanged(adapPos)
isUpdated = false
}
}
override fun onStart() {
super.onStart()
if(isReturning)
{
adapter!!.updateResults(this.listItems!!)
adapter!!.notifyDataSetChanged()
}
adapter = PediaAdapter(this, listItems!!)
layoutManager = LinearLayoutManager(this)
recyclerViewID.adapter = adapter
recyclerViewID.layoutManager = layoutManager
list = dbHandler.readAllNotes()
for(reader in list!!.iterator())
{
var note = UserNotes()
note.noteTitle = reader.noteTitle
note.noteText = reader.noteText
note.noteID = reader.noteID
note.noteDate = reader.noteDate
listItems!!.add(note)
}
adapter!!.notifyDataSetChanged()
if(dbHandler.totalNotes() == 0) {
recyclerViewID.visibility = View.GONE
}
else{
recyclerViewID.visibility = View.VISIBLE
showWhenEmptyID.visibility = View.GONE
}
recyclerViewID.hasFixedSize()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == REQUEST_CODE)
if(resultCode == Activity.RESULT_OK)
{
//isCreated = data!!.extras!!.getBoolean("isCreated")
updatedTitle = data!!.extras.getString("updatedTitle")
updatedText = data!!.extras.getString("updatedText")
isReturning = data.extras!!.getBoolean("returningBack")
// isUpdated = data.extras!!.getBoolean("isUpdated")
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.top_menu, menu)
val item = menu!!.findItem(R.id.delete_note_menu)
item.setVisible(false)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
if(item!!.itemId == R.id.add_note_menu){
isNewNote = true
startActivity(Intent(this, ReferenceActivity::class.java))
}
if(item!!.itemId == R.id.delete_note_menu)
{
Toast.makeText(this,"DELETED", Toast.LENGTH_SHORT).show()
}
return super.onOptionsItemSelected(item)
}
private fun showOneTimeMessage()
{
var data: SharedPreferences = getSharedPreferences(PREFS_NAME, 0)
if(data.contains("isShown"))
{
first_run = data.getBoolean("isShown", true)
}
Log.d("FIRST_RUN", first_run.toString())
if(first_run)
{
val oneTimeMsg = SweetAlertDialog(this)
oneTimeMsg.setTitleText("Hey there!")
oneTimeMsg.setContentText("Thank you for downloading! Please don`t forget to rate our app :)").show()
oneTimeMsg.setConfirmClickListener(object : SweetAlertDialog.OnSweetClickListener
{
override fun onClick(sweetAlertDialog: SweetAlertDialog?)
{
oneTimeMsg.dismissWithAnimation()
}
}).show()
myPrefs = getSharedPreferences(PREFS_NAME, 0)
var editor: SharedPreferences.Editor = (myPrefs as SharedPreferences).edit()
editor.putBoolean("isShown", false)
editor.commit()
}
}
REFERENCE ACTIVITY
class ReferenceActivity : AppCompatActivity() {
var dbHandler: PediaDatabase? = null
var note = UserNotes()
var noteExisted: Boolean = false
var cardAdapterPos: Int? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_reference)
getSupportActionBar()!!.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM)
getSupportActionBar()!!.setCustomView(R.layout.custom_toolbar)
val dateTxtView = findViewById<View>(resources.getIdentifier("action_bar_title", "id", packageName)) as TextView
overridePendingTransition(R.anim.slide_in, R.anim.slide_out)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
window.navigationBarColor = Color.BLACK
dbHandler = PediaDatabase(this)
val data = intent
if(isNewNote != true/*isNewNote.extras.getBoolean("isNewNote") != true*/)
{
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
if(data != null)
{
noteExisted = true
this.cardAdapterPos = data.extras.getInt("cardPosition")
cardID = data.extras.getInt("cardID")
existingNote = dbHandler!!.readNote(cardID)
refTitleID.setText(existingNote.noteTitle, TextView.BufferType.EDITABLE)
refTextID.setText(existingNote.noteText, TextView.BufferType.EDITABLE)
dateTxtView.text = existingNote.noteDate.toString()
}
}else{
dateTxtView.text = "New note"
}
}
override fun onStop() {
super.onStop()
var title: String = refTitleID.text.toString().trim()
var text: String = refTextID.text.toString().trim()
if(existingNote.noteText == text && existingNote.noteTitle == title)
finish()
if(noteExisted)
{
if(TextUtils.isEmpty(title))
title = "No title"
existingNote.noteTitle = title
existingNote.noteText = text
existingNote.noteDate = System.currentTimeMillis().toString() //TODO TRY THIS
dbHandler!!.updateNote(existingNote)
var dataCreate = this.intent
dataCreate.putExtra("isUpdated", true)
dataCreate.putExtra("updatedTitle", title)
dataCreate.putExtra("updatedText",text)
dataCreate.putExtra("returningBack", true)
setResult(Activity.RESULT_OK, dataCreate)
finish()
}
else
{
if(TextUtils.isEmpty(title) && TextUtils.isEmpty(text))
{
finish()
}
else
{
if(TextUtils.isEmpty(title))
title = "No title"
note.noteTitle = title
note.noteText = text
note.noteDate = System.currentTimeMillis().toString()
// note.noteID =
dbHandler!!.createNote(note)
var dataCreate = this.intent
dataCreate.putExtra("isCreated", true)
dataCreate.putExtra("returningBack", true)
setResult(Activity.RESULT_OK, dataCreate)
finish()
}
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.top_menu, menu)
val addItem: MenuItem = menu!!.findItem(R.id.add_note_menu)
val delItem:MenuItem = menu.findItem(R.id.delete_note_menu)
addItem.setVisible(false)
delItem.setVisible(false)
if(noteExisted)
delItem.setVisible(true)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
if(item!!.itemId == R.id.delete_note_menu)
{
val dialogMsg = SweetAlertDialog(this, SweetAlertDialog.WARNING_TYPE)
dialogMsg.setTitleText("Are you sure?")
dialogMsg.setContentText("You won`t be able to recover this note!")
dialogMsg.setConfirmText("Yes, delete it!")
dialogMsg.setConfirmClickListener(object: SweetAlertDialog.OnSweetClickListener {
override fun onClick(sweetAlertDialog: SweetAlertDialog?) {
dialogMsg.dismissWithAnimation()
dbHandler!!.deleteNote(cardID)
val successMsg = SweetAlertDialog(sweetAlertDialog!!.context, SweetAlertDialog.SUCCESS_TYPE)
successMsg.setTitleText("Note deleted!")
successMsg.setContentText("So long,note").show()
successMsg.setCancelable(false)
//TODO Disable 'OK' button on successMsg dialogbox
Handler().postDelayed({
successMsg.dismissWithAnimation()
finish()
}, 1200)
}
}).show()
}
return super.onOptionsItemSelected(item)
}
ADAPTER
class PediaAdapter(private val context: Context,
private var noteslist: ArrayList<UserNotes>): RecyclerView.Adapter<PediaAdapter.ViewHolder>() {
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder
{
val view = LayoutInflater.from(context).inflate(R.layout.list_row,p0,false)
return ViewHolder(view, noteslist)
}
override fun getItemCount(): Int
{
return noteslist.size
}
override fun onBindViewHolder(p0: ViewHolder, p1: Int)
{
p0.bindItems(noteslist[p1])
}
inner class ViewHolder(itemView: View, list: ArrayList<UserNotes>): RecyclerView.ViewHolder(itemView), View.OnClickListener
{
private var noteTitle = itemView.findViewById(R.id.listTitleID) as TextView
private var noteText = itemView.findViewById(R.id.listTextID) as TextView
var mList = list
init
{
itemView.setOnClickListener(this)
}
fun bindItems(note: UserNotes)
{
//var id = note.noteID
noteTitle.text = note.noteTitle
noteText.text = note.noteText
}
override fun onClick(v: View?)
{
var mPosition: Int = adapterPosition //For forwarding position to ref activity
var note = mList[mPosition]
adapPos = adapterPosition
var cardID = Intent(itemView.context, ReferenceActivity::class.java)
cardID.putExtra("cardPosition", mPosition)
cardID.putExtra("cardID", note.noteID) //TODO THIS IS FETCHING NOTE_ID VALUES FROM DB
Toast.makeText(itemView.context, "card id = " + note.noteID, Toast.LENGTH_SHORT).show()
itemView.context.startActivity(cardID)
}
}
fun updateResults(items: ArrayList<UserNotes>)
{
this.noteslist = items
}
Yes, I know its hard to go through someones code. I have tried to fix it many times sitting all day trying to figure it out and still no luck. I am requesting you to please help me with this. I don't care if you do in Java, I just need a way to fix it.
Declare your MainActivity in AndroidManifest.xml file like this.
android:launchMode="singleTask"
Before Finishing 'ReferenceActivity' (i.e calling finish()), make an Intent call to your 'MainActivity'. Also, override 'onNewIntent()' method inside your 'MainActivity'.
#Override
protected void onNewIntent(Intent intent)
Inside 'onNewIntent()' method, load you data again as you're already doing in 'onStart()' and 'onRestart()'.
Explanation, What we're doing is adding a single reference of our 'MainActivity' in Activity Stack, so whenever an intent call is made to 'MainActivity' instead of creating multiple reference it just create one reference and call newIntentMethod every time.
Hopefully, that will fix your issue.