GeoQuiz Challenge 1: Toast Gravity doesn't change

This is my solution for challenge 1:

class MainActivity : AppCompatActivity() {
    private lateinit var trueButton : Button;
    private lateinit var falseButton : Button;
    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)

        trueButton.setOnClickListener { view: View ->
            val myToast1=Toast.makeText(this,R.string.correct_toast,Toast.LENGTH_SHORT)
            myToast1.setGravity(Gravity.TOP,0,0)
            myToast1.show()}
        falseButton.setOnClickListener { view: View ->
            val myToast2=Toast.makeText(this,R.string.incorrect_toast,Toast.LENGTH_SHORT)
            myToast2.setGravity(Gravity.TOP,0,0)
            myToast2.show()}
    }
}

It SHOULD work, but in the emulator, the toast still shows up in the default position (bottom of the screen). I’ve tried other people’s solutions too and those don’t seem work for me either. What am I doing wrong?
I’ve tried using setText() on the toast and that works just fine, but setGravity() doesn’t

1 Like

Solved! (kinda)
While the virtual device (pixel 3a) refused to show the toast anywhere else, I’ve tried it on my physical OnePlus5 and it works now.

I stumbled on this also. Check this:
https://developer.android.com/reference/kotlin/android/widget/Toast#setgravity

It states

Warning: Starting from Android Build.VERSION_CODES#R , for apps targeting API level Build.VERSION_CODES#R or higher, this method is a no-op when called on text toasts.

The default virtual device is the Pixel 3a, running Android API 30 (R), that’s why setGravity has no effect (is no-op).
My recommendation is to go back some pages and create the virtual device as the book teaches, running Android API 28 (Pie).

It works in your device probably because it’s still running Android Q, at the most.

2 Likes

Thanks for the answer, I’ll either use an older API then, or avoid using virtual device entirely. (I always have my phone with me anyway)

1 Like

Thanks for posting this. I had the same solution and the same problem! It works on my physical phone. It’s a relatively new phone. I also saw the warning on the developer.android site. I’m a little unclear on its meaning. What would be the alternative solution when running a newer virtual device?

I also saw the warning on the developer.android site. Thanks for brining it up. I’m a little unclear on the message’s meaning. What would be an alternative solution when running a newer virtual device?

In the Android docs for Toast

https://developer.android.com/reference/android/widget/Toast

it recommends switching to Snackbar for short messages as in

Note that [Snackbars] are preferred for brief messages while the app is in the foreground.

1 Like

Snackbars are better, since they provide a message like Toast, but you can add action to it, in addition it looks better than toast.

check this out, I checked out how snackbar can be made, and i added the toast within its action.

trueButton.setOnClickListener {
                Snackbar.make(it, R.string.correct_toast, Snackbar.LENGTH_LONG)
                    .setAction("Show Toast") {
                        val toastTrue = Toast.makeText(this, R.string.correct_toast, Toast.LENGTH_SHORT)
                        toastTrue.setGravity(Gravity.TOP,0,0)
                        toastTrue.show()
                    }
                    .show()
                }
2 Likes

I like the looks of the above code with Snackbars but I still can’t get it to print anyplace except the bottom.

1 Like

SnackBar is different than Toast in relation to positioning… you have to create the area that you want to display the Snackbar in it within the view and use it on the code

I did this as a small example if you want to display the Snackbar at the top

this is the view file, i added a coordinated widget and a button within a constrained layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/myCoordinatorLayout"
        android:layout_width="407dp"
        android:layout_height="80dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/SnackButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ShowSnack"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/myCoordinatorLayout" />

</androidx.constraintlayout.widget.ConstraintLayout>

then i defined them in the code and used the CorrdinatorLayout for the snackbar

package com.bignerdranch.android.snackbar

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.google.android.material.snackbar.Snackbar


class MainActivity : AppCompatActivity() {
    private lateinit var viewPros : View
    private lateinit var SnackButton : Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewPros = findViewById(R.id.myCoordinatorLayout)
        SnackButton = findViewById(R.id.SnackButton)

        SnackButton.setOnClickListener {
            Snackbar.make(viewPros, "Your Message", Snackbar.LENGTH_LONG)
                .setAction("Action"){
                    Toast.makeText(this, "BRAVO", Toast.LENGTH_SHORT).show()
                }
                .show();
        }

    }
}
2 Likes

I updated my build.gradle (:app) file to the following and it works for me. Specifically, I changed targetSdkVersion to 29.

    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.example.geoquiz"
        minSdkVersion 24
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

you can also try:

Toast.makeText(this,
R.string.resource-id,
Toast.LENGTH_SHORT ).apply{
setGravity(TOP,
0,
0).show()}