65

I want to check if a View within a ScrollView is currently visible in Android. I am not checking if it is focused on yet but if it is currently being displayed on screen. Is there a method in View that can tell me if the view is currently visible?

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
user1847544
  • 957
  • 2
  • 9
  • 17

7 Answers7

76

This code works for me:

public static boolean isVisible(final View view) {
    if (view == null) {
        return false;
    }
    if (!view.isShown()) {
        return false;
    }
    final Rect actualPosition = new Rect();
    view.getGlobalVisibleRect(actualPosition);
    final Rect screen = new Rect(0, 0, getScreenWidth(), getScreenHeight());
    return actualPosition.intersect(screen);
}
zegee29
  • 934
  • 7
  • 8
  • 6
    Note to get the screen width and height use: `Resources.getSystem().getDisplayMetrics().widthPixels` and `Resources.getSystem().getDisplayMetrics().heightPixels` – Bruno Bieri Mar 04 '20 at 09:57
  • 1
    It's working like a charm, after context changes, in recyclerviews, in viewpagers, everywhere. Unbelievable! – asozcan Mar 24 '20 at 11:52
  • I believe this should be the accepted answer. It works perfectly! – Firzen Apr 16 '20 at 11:22
  • Really valuable answer, works good unlike getGlobalVisibleRect itself. – Bitlejuce Do Apr 30 '20 at 17:22
  • don't use "intersect" if you want to just check for intersection. Use "intersects" instead. Only use "intersect" if you would like to record intersection – Prakash Dec 08 '20 at 18:32
22
int[] location = new int[2];
view.getLocationOnScreen(location);

or

Rect rect = new Rect();
view.getGlobalVisibleRect(rect);

Now use this location or rectangle to check if it is in your visible bounds or not. If it is simply the entire screen, check against getResources().getDisplayMetrics().

As pointed by Antek in the comments below, the view may still be gone or invisible with the returned values here telling where it was last drawn. So combining the above bounds-related condition with an view.isShown() or view.getVisibility() == VISIBLE should take care of that.

AA_PV
  • 1,339
  • 1
  • 16
  • 24
  • 2
    this does not work when toggling visibility - if your view was initially visible, then it will retain its visible rect dimensions. – Antek Jul 18 '17 at 11:04
  • You can sure add a check for view's visibility as well – AA_PV Jul 18 '17 at 13:24
  • what do you mean? The view has now `visibility = GONE` (I just toggled it, it had `visibility = VISIBLE`), yet the visible rectangle remains as it was when the view was created. No need to check it, as I set it myself in one place in code. – Antek Jul 18 '17 at 13:44
  • 1
    I meant depending on the intention, you can add the check for view.getVisibility() == VISIBLE along with the position returned on screen. For the question actually it would make sense to add it, I'll edit the answer. Thanks – AA_PV Jul 18 '17 at 15:39
  • @Antek It would be interesting to test this out if you're working around this - what happens when the view is drawn, then made GONE then never drawn again? I imagined GONE would update the location but if it doesn't it worth checking if we stay with a stale location going forward. Thanks! – AA_PV Jul 18 '17 at 15:46
  • changing the visibility to GONE doesn't change the location, actually - for my particular case it's `0,0` either way (fullscreen view group) – Antek Jul 18 '17 at 16:19
  • and actually I will just wait a bit (100 ms?) in background thread, because I noticed that I don't need to check explicitly for the view being drawn or not - the issue is (most probably) caused by calling this chunk of code many times in a second from another place. – Antek Jul 18 '17 at 16:21
  • 0,0! Either ways my edit holds for an invisible view :P – AA_PV Jul 19 '17 at 00:25
  • well, my understanding is that by `location` they meant upper-left corner of a view (which can have some dimensions) - so any view located there, regardless of size, will have such location. – Antek Jul 19 '17 at 08:18
  • yep... try getting the visible Rect instead in your case – AA_PV Jul 23 '17 at 07:07
  • do you mean `boundingBox`? – Antek Jul 25 '17 at 08:41
17

zegee29's answer is quite helping. Although I'd like to suggest using the result of view.getGlobalVisibleRect(actualPosition) too, because in some cases Rect.intersects() returns true when item is not visible at all, so the resulting code is:

fun View.isVisible(): Boolean {
    if (!isShown) {
        return false
    }
    val actualPosition = Rect()
    val isGlobalVisible = getGlobalVisibleRect(actualPosition)
    val screenWidth = Resources.getSystem().displayMetrics.widthPixels
    val screenHeight = Resources.getSystem().displayMetrics.heightPixels
    val screen = Rect(0, 0, screenWidth, screenHeight)
    return isGlobalVisible && Rect.intersects(actualPosition, screen)
}

Or you may just the result of getGlobalVisibleRect(actualPosition)

2

Java variant of Диана Ганиева post https://stackoverflow.com/a/66907184/2323972

boolean isViewOnScreen(View target)
{
       if (!target.isShown())
        {
            return false;
        }
        final var actualPosition = new Rect();
        final var isGlobalVisible = target.getGlobalVisibleRect(actualPosition);
        final var screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
        final var screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
        final var screen = new Rect(0, 0, screenWidth, screenHeight);
        return isGlobalVisible && Rect.intersects(actualPosition, screen);
}
Mic
  • 105
  • 1
  • 6
-11

try

if(view.isShown()) {
    // Visible
} else { 
    // Invisible
}
Rohit Suthar
  • 2,635
  • 1
  • 22
  • 27
-22

public boolean checkVisiblity(View view){

if(view.isShown()) return true; else return false;

}

-31

The function View.getVisibility() can have below values:

  • View.VISIBLE (0): the view is visible.

  • View.INVISIBLE (1): The view is invisible, but it still takes up space for layout purposes.

  • View.GONE (2): the view is gone. Completely hidden, as if the view had not been added

You can see below link for more info. How can I check if a view is visible or not in Android?

Community
  • 1
  • 1
secretlm
  • 2,361
  • 2
  • 27
  • 38
  • 9
    Why not give credit to the original answer? http://stackoverflow.com/a/3791698/562935 – tidbeck Jun 25 '13 at 08:57
  • 6
    @tidbeck this answer is completely wrong! he wants to know view is visibile right now in screen or not! visibility attribute always return visible if you don't change it. this attribute is not related to scroll,it only modify by programmer. – Siavash Abdoli Jan 26 '16 at 07:23
  • 1
    By the way, constants for visible, invisible and gone are 0,4 and 8 respectively. – GAMA Mar 04 '16 at 13:13