3

I have RecyclerView and, in some cases, I show another view on top of it - ProgressDialog, AlertDialog or DialogFragment.

Is there some way to notify me about cases when my RecyclerView is at front or another view is above it now?

I tried to add onFocusChangeListener() to my RecyclerView, but no luck.

PS. Definitely, I can in my RecyclerView create some method isOnFront(boolean onFront) and in all my other views call it, but maybe there is some more elegance way?

azizbekian
  • 60,783
  • 13
  • 169
  • 249
Goltsev Eugene
  • 3,325
  • 6
  • 25
  • 48
  • I have tricky solution, If your cases are just like displaying `ProgressDialog`, `AlertDialog` or `DialogFragment`, then you should override `onPause()` and `onResume()` of activity or fragment where your `Recyclerview` is implemented. Showing dialog will call onPause() method, and dismissing that dialog will call `onResume()` of that activity, from this you will able to know whether `Recyclerview` is in focus or not. – Moinkhan Jun 05 '17 at 05:20
  • No, that won't work, as I show dialog from the same activity. Moreover, as dialogs should be modal, I add them via `FragmentManager.add()` instead of `FragmentManager.replace()`. So `onPause()` is not calling at all. – Goltsev Eugene Jun 05 '17 at 18:49
  • Ok so for fragment you can work on backstack count. You can figure out whether fragment is present or not. – Moinkhan Jun 05 '17 at 18:54
  • If you show `AlertDialog`, for instance, fragments' backstack would not be changed. – Goltsev Eugene Jun 06 '17 at 09:12
  • 1
    To whom has this problem, this helped me: https://stackoverflow.com/a/65005551/8551764 – Mostafa Arian Nejad Nov 25 '20 at 13:35

2 Answers2

2

ProgressDialog, AlertDialog and DialogFragment would lay their content on the Window, not to your activity's/fragment's view hierarchy. Which means, that as soon as either of them is shown, the focus of Window is changed. Hence, you can make use of ViewTreeObserver#addOnWindowFocusChangeListener() API:


    contentView.getViewTreeObserver().addOnWindowFocusChangeListener(
        new ViewTreeObserver.OnWindowFocusChangeListener() {
          @Override public void onWindowFocusChanged(boolean hasFocus) {
            // Remove observer when no longer needed
            // contentView.getViewTreeObserver().removeOnWindowFocusChangeListener(this);

            if (hasFocus) {
              // Your view hierarchy is in the front
            } else {
              // There is some other view on top of your view hierarchy,
              // which resulted in losing the focus of window
            }
          }
        });

azizbekian
  • 60,783
  • 13
  • 169
  • 249
  • Thanks, will give it a try! – Goltsev Eugene Jun 05 '17 at 18:49
  • Yes, this makes a trick, but one small thing - `addOnWindowFocusChangeListener` needs API level 18. Any idea for earlier APIs? – Goltsev Eugene Jun 07 '17 at 13:56
  • I suppose [`getWindow().getCurrentFocus()`](https://developer.android.com/reference/android/view/Window.html#getCurrentFocus()) will do the trick. It will return `null` if there does **not** exist a view with a focus. – azizbekian Jun 07 '17 at 14:04
1

I think you should rethink your software design. If YOU trigger dialogs to be shown on top of another views, then you SHOULD know if the are shown or not. Another question is: Why should your RecyclerView know something about other views in your application?

If you really want to know, if your dialog is shown or not, set a boolean variable in your Fragment (or Activity), when you show it. Or use the field itself as indicator (myDialog != null equals "myDialog is shown"). Set it to null if you dismiss your dialog. If you really need to let other Fragments or Views know, that you show a dialog on top of them you can use any kind of event bus to broadcast this event.

I do not recommend tampering with any kind of ViewTreeObserver listeners or FragmentBackstack listeners for getting this result.

artkoenig
  • 7,117
  • 2
  • 40
  • 61