Skip to content

Request: support Android 11 (R - API 31)  #1

Closed

Description

@AndroidDeveloperLB

Sadly on Android R, you can't set a custom View for a Toast (when targeting API 31) :

https://developer.android.com/reference/android/widget/Toast#setView(android.view.View)
https://developer.android.com/reference/android/widget/Toast#getView()

Please offer something that mimics the standard Toast's look&feel, so that at least we could have it shown within the app, as a normal View.
Maybe something similar to what we have when we long press the action items on the toolbar:

dfu6CwFaPM.zip

Custom Toasts are useful anyway usually only when the user is inside the app...

Activity

  1. marcoscgdev commented on Dec 3, 2020

    @marcoscgdev
    Owner

    Fixed in version 1.0.2. Thank you! 👍

  2. AndroidDeveloperLB commented on Dec 3, 2020

    @AndroidDeveloperLB
    Author

    How did you fix it?
    Have you implemented a custom View for Toast, that isn't really a Toast, and shown only inside the app itself?

  3. marcoscgdev commented on Dec 4, 2020

    @marcoscgdev
    Owner

    How did you fix it?
    Have you implemented a custom View for Toast, that isn't really a Toast, and shown only inside the app itself?

    I have used a PopupWindow with a custom view inside. I did some research and it seems to be the best option, because unfortunately it is no longer possible to use a custom view in a Toast.

  4. AndroidDeveloperLB commented on Dec 4, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev
    It might be possible using reflection, but it's a path I wouldn't recommend, especially now that Google tries to protect vs such things...

    Anyway, thank you for this.
    Is it possible to use your solution to position it near a View, like what we see when we long press an action-item of a Toolbar (which shows explanation of what it is) ?

  5. marcoscgdev commented on Dec 4, 2020

    @marcoscgdev
    Owner

    @marcoscgdev
    It might be possible using reflection, but it's a path I wouldn't recommend, especially now that Google tries to protect vs such things...

    Anyway, thank you for this.
    Is it possible to use your solution to position it near a View, like what we see when we long press an action-item of a Toolbar (which shows explanation of what it is) ?

    At this time it is not possible to do that. However, I will work on it for future versions 👌

  6. AndroidDeveloperLB commented on Dec 5, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev Well if you have a custom view now, you can try using something like what was used for toast, at least as offered by others:

        @SuppressLint("RtlHardcoded")
        fun positionToast(toast: Toast, view: View, activity: Activity, offsetX: Int, offsetY: Int) {
            val toastView = toast.view ?: return
            val rect = Rect()
            val window = activity.window
            window.decorView.getWindowVisibleDisplayFrame(rect)
            val viewLocation = IntArray(2)
            view.getLocationInWindow(viewLocation)
            val viewLeft = viewLocation[0] - rect.left
            val viewTop = viewLocation[1] - rect.top
            val windowMetricsSize = Utils.getWindowMetricsSize(activity)
            val widthMeasureSpec = MeasureSpec.makeMeasureSpec(windowMetricsSize.x, MeasureSpec.UNSPECIFIED)
            val heightMeasureSpec = MeasureSpec.makeMeasureSpec(windowMetricsSize.y, MeasureSpec.UNSPECIFIED)
            toastView.measure(widthMeasureSpec, heightMeasureSpec)
            val toastWidth = toastView.measuredWidth
            val toastHeight = toastView.measuredHeight
            val toastX = viewLeft + (view.width - toastWidth) / 2 + offsetX
            val toastY = viewTop + (view.height - toastHeight) / 2 + offsetY
            toast.setGravity(Gravity.LEFT or Gravity.TOP, toastX, toastY)
        }

    It might have some bug though. I haven't tested it much.

  7. marcoscgdev commented on Dec 5, 2020

    @marcoscgdev
    Owner

    @marcoscgdev Well if you have a custom view now, you can try using something like what was used for toast, at least as offered by others:

        @SuppressLint("RtlHardcoded")
        fun positionToast(toast: Toast, view: View, activity: Activity, offsetX: Int, offsetY: Int) {
            val toastView = toast.view ?: return
            val rect = Rect()
            val window = activity.window
            window.decorView.getWindowVisibleDisplayFrame(rect)
            val viewLocation = IntArray(2)
            view.getLocationInWindow(viewLocation)
            val viewLeft = viewLocation[0] - rect.left
            val viewTop = viewLocation[1] - rect.top
            val windowMetricsSize = Utils.getWindowMetricsSize(activity)
            val widthMeasureSpec = MeasureSpec.makeMeasureSpec(windowMetricsSize.x, MeasureSpec.UNSPECIFIED)
            val heightMeasureSpec = MeasureSpec.makeMeasureSpec(windowMetricsSize.y, MeasureSpec.UNSPECIFIED)
            toastView.measure(widthMeasureSpec, heightMeasureSpec)
            val toastWidth = toastView.measuredWidth
            val toastHeight = toastView.measuredHeight
            val toastX = viewLeft + (view.width - toastWidth) / 2 + offsetX
            val toastY = viewTop + (view.height - toastHeight) / 2 + offsetY
            toast.setGravity(Gravity.LEFT or Gravity.TOP, toastX, toastY)
        }

    It might have some bug though. I haven't tested it much.

    This is very easy to do with PopupWindow. Simply call this method to display the alert next to a view:

    popupWindow.showAsDropDown(yourView)

    This feature, along with code migration to Kotlin will be available in the next release.

  8. AndroidDeveloperLB commented on Dec 5, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev Does it get positioned nicely? Even if the view is at the corner?
    Can you please let me know when this feature is ready?

  9. marcoscgdev commented on Dec 5, 2020

    @marcoscgdev
    Owner

    @marcoscgdev Does it get positioned nicely? Even if the view is at the corner?
    Can you please let me know when this feature is ready?

    Yes, apparently it fits the view well. I don't know when I'm going to release a new version, but I've just make a commit with these changes and you can try them out in this non-definitive version:

    implementation 'com.github.marcoscgdev:MaterialToast:b7a2bab65b'

    Tell me if everything works fine for you 😄

  10. AndroidDeveloperLB commented on Dec 5, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev Can you please show a snippet, of how to show your toast for some View? Something similar to what we see when we long press the action-item of a toolbar?

  11. marcoscgdev commented on Dec 5, 2020

    @marcoscgdev
    Owner

    @marcoscgdev Can you please show a snippet, of how to show your toast for some View? Something similar to what we see when we long press the action-item of a toolbar?

    Sure. Just call show(yourView).

    Ful example:

    MaterialToast.makeText(activity, "Hello, I'm a material toast!", R.mipmap.ic_launcher, Toast.LENGTH_SHORT).show(yourView)

    or

    MaterialToast(this)
            .setMessage("Hello, I'm a material toast!")
            .setIcon(R.mipmap.ic_launcher)
            .setDuration(Toast.LENGTH_SHORT)
            .setBackgroundColor(Color.RED)
            .show(yourView)

    If you want to show it on long click listener:

    yourView.setOnLongClickListener {
        MaterialToast.makeText(activity, "Hello, I'm a material toast!", R.mipmap.ic_launcher, Toast.LENGTH_SHORT).show(yourView)
        true
    }
  12. AndroidDeveloperLB commented on Dec 6, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev I failed to use it this way. See attached. It doesn't do anything...

    My Application.zip

  13. marcoscgdev commented on Dec 6, 2020

    @marcoscgdev
    Owner

    @marcoscgdev I failed to use it this way. See attached. It doesn't do anything...

    My Application.zip

    The Toast is always displayed below the view, so if the view is at the bottom of the screen, the Toast will not be displayed.

    Screenshot_1607283800

    fun positionToast(toast: Toast, view: View, activity: Activity, offsetX: Int, offsetY: Int)

    I have implemented this approach. Please try with this version:

    implementation 'com.github.marcoscgdev:MaterialToast:e128609003'

  14. AndroidDeveloperLB commented on Dec 6, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev I don't get how to use it.
    It doesn't show up. I don't think this function exists.

  15. marcoscgdev commented on Dec 6, 2020

    @marcoscgdev
    Owner

    @marcoscgdev I don't get how to use it.
    It doesn't show up. I don't think this function exists.

    Of course this function exists, I have created it! 😄 You can check it here.

    If you run your project using the latest version I left you in the previous message, it should work.

    implementation 'com.github.marcoscgdev:MaterialToast:e128609003'

  16. AndroidDeveloperLB commented on Dec 6, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev Either I don't understand how to use it, or it doesn't exist.
    See:

    image

    Please show how to use it.

  17. marcoscgdev commented on Dec 7, 2020

    @marcoscgdev
    Owner

    @marcoscgdev Either I don't understand how to use it, or it doesn't exist.
    See:

    image

    Please show how to use it.

    I have explained to you before how it works. Your code in "My Application.zip" project is OK. I have tested it and it works. When you click on the button, the Toast will appear next to it.

  18. AndroidDeveloperLB commented on Dec 7, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev I can't find "positionToast" anywhere.
    Using my sample, I can't find how far I want the Toast to be (say, at least 12dp, for example) from the View.
    Maybe you added it in a different name?

    See:

    image

    image

    Attached new project:

    My Application.zip

  19. marcoscgdev commented on Dec 7, 2020

    @marcoscgdev
    Owner

    @marcoscgdev I can't find "positionToast" anywhere.
    Using my sample, I can't find how far I want the Toast to be (say, at least 12dp, for example) from the View.
    Maybe you added it in a different name?

    See:

    image

    image

    Attached new project:

    My Application.zip

    I have not added the possibility of changing the distance to the view. The distance is always fixed, it only depends on the position of the view.

  20. AndroidDeveloperLB commented on Dec 7, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev Can you please add it, or at least make it have the same look&feel like the one of Google, a bit far ?

    See here when you long press a Toolbar action item when it's at the top:

    image

    image

    And this is when I put it at the bottom:

    image

    image

  21. marcoscgdev commented on Dec 8, 2020

    @marcoscgdev
    Owner

    View offset has been added. Here are some examples:

    .show(view)
    .show(view, offsetY = -60)
    .show(view, offsetX = 20, offsetY = 50)

     implementation 'com.github.marcoscgdev:MaterialToast:9e0879bdd7'
  22. AndroidDeveloperLB commented on Dec 9, 2020

    @AndroidDeveloperLB
    Author

    @marcoscgdev
    I've now tested it. Not sure how to set the positions properly.
    If you've used the same code I wrote, note that I just copied it from somewhere else, and I don't think it should be up to the library to position it this way
    The custom View works fine though.

    Can you please set it to be to (0,0) by default, so that the toast x,y will be positioned exactly on the same x,y of the target View?
    Maybe let whoever uses it to decide how to put it.
    Maybe on the sample you can demonstrate how to do it nicely (like checking where the target View is, and based on this to decide where to put the Toast) .

    See attached. It seems that if the target View is at the bottom right, it puts the toast on center-horizontal of them, and sets the Y to be a bit above the target View:

    image

    My Application.zip

  23. AndroidDeveloperLB commented on Dec 9, 2020

    @AndroidDeveloperLB
    Author

    I think this is nicer (when using a real Toast) about the auto-location (but again, should be optional to have it auto-position) :

        @SuppressLint("RtlHardcoded")
        fun positionToast(toast: Toast, view: View, window: Window, offsetX: Int, offsetY: Int) {
            val toastView = toast.view ?: return
            val rect = Rect()
            window.decorView.getWindowVisibleDisplayFrame(rect)
            val viewLocation = IntArray(2)
            view.getLocationInWindow(viewLocation)
            val viewLeft = viewLocation[0] - rect.left
            val viewTop = viewLocation[1] - rect.top
            val metrics = DisplayMetrics()
            window.windowManager.defaultDisplay.getMetrics(metrics)
            val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.UNSPECIFIED)
            val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(metrics.heightPixels, View.MeasureSpec.UNSPECIFIED)
            toastView.measure(widthMeasureSpec, heightMeasureSpec)
            val toastWidth = toastView.measuredWidth
            val toastHeight = toastView.measuredHeight
            val closerToLeft = viewLeft < metrics.widthPixels / 2
            val closerToTop = viewTop < metrics.heightPixels / 2
            val toastX = if (closerToLeft) viewLeft + view.width + offsetX else viewLeft - toastWidth - offsetX
            val toastY = if (closerToTop) viewTop + view.height + offsetY else viewTop - toastHeight - offsetX
            toast.setGravity(Gravity.LEFT or Gravity.TOP, toastX, toastY)
        }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions