What's the best way to check if the view is visible on the window?

Viewed 24973

What's the best way to check if the view is visible on the window?

I have a CustomView which is part of my SDK and anybody can add CustomView to their layouts. My CustomView is taking some actions when it is visible to the user periodically. So if view becomes invisible to the user then it needs to stop the timer and when it becomes visible again it should restart its course.

But unfortunately there is no certain way of checking if my CustomView becomes visible or invisible to the user. There are few things that I can check and listen to:

onVisibilityChange //it is for view's visibility change, and is introduced in new API 8 version so has backward compatibility issue
onWindowVisibilityChange //but my CustomView can be part of a ViewFlipper's Views so it can pose issues
onDetachedFromWindows //this not as useful
onWindowFocusChanged //Again my CustomView can be part of ViewFlipper's views.
So if anybody has faced this kind of issues please throw some light.

9 Answers

This solution takes into account view obstructed by statusbar and toolbar, also as view outside the window (e.g. scrolled out of screen)

/**
 * Test, if given {@code view} is FULLY visible in window. Takes into accout window decorations
 * (statusbar and toolbar)
 *
 * @param view
 * @return true, only if the WHOLE view is visible in window
 */
public static boolean isViewFullyVisible(View view) {
    if (view == null || !view.isShown())
        return false;

    //windowRect - will hold available area where content remain visible to users
    //Takes into account screen decorations (e.g. statusbar)
    Rect windowRect = new Rect();
    view.getWindowVisibleDisplayFrame(windowRect);

    //if there is toolBar, get his height
    int actionBarHeight = 0;
    Context context = view.getContext();
    if (context instanceof AppCompatActivity && ((AppCompatActivity) context).getSupportActionBar() != null)
        actionBarHeight = ((AppCompatActivity) context).getSupportActionBar().getHeight();
    else if (context instanceof Activity && ((Activity) context).getActionBar() != null)
        actionBarHeight = ((Activity) context).getActionBar().getHeight();

    //windowAvailableRect - takes into account toolbar height and statusbar height
    Rect windowAvailableRect = new Rect(windowRect.left, windowRect.top + actionBarHeight, windowRect.right, windowRect.bottom);

    //viewRect - holds position of the view in window
    //(methods as getGlobalVisibleRect, getHitRect, getDrawingRect can return different result,
    // when partialy visible)
    Rect viewRect;
    final int[] viewsLocationInWindow = new int[2];
    view.getLocationInWindow(viewsLocationInWindow);
    int viewLeft = viewsLocationInWindow[0];
    int viewTop = viewsLocationInWindow[1];
    int viewRight = viewLeft + view.getWidth();
    int viewBottom = viewTop + view.getHeight();
    viewRect = new Rect(viewLeft, viewTop, viewRight, viewBottom);

    //return true, only if the WHOLE view is visible in window
    return windowAvailableRect.contains(viewRect);
}
Related