Как узнать, отображается ли представление на экране в Android?

Я хочу проверить, отображается ли в настоящее время View внутри ScrollView в Android. Я не проверяю, сфокусирован ли он еще, но отображается ли он в данный момент на экране. Есть ли в View метод, который может сказать мне, видимо ли представление в данный момент?


person user1847544    schedule 26.12.2012    source источник
comment
Посмотрите на эту ссылку - stackoverflow.com/a/4629167/614807   -  person Chirag    schedule 26.12.2012


Ответы (6)


Этот код работает для меня:

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);
}
person zegee29    schedule 28.02.2018
comment
Обратите внимание, чтобы получить ширину и высоту экрана, используйте: Resources.getSystem().getDisplayMetrics().widthPixels и Resources.getSystem().getDisplayMetrics().heightPixels - person Bruno Bieri; 04.03.2020
comment
Это работает как шарм, после изменения контекста, в повторных просмотрах, в пейджерах, везде. Невероятный! - person asozcan; 24.03.2020
comment
Я считаю, что это должен быть принятый ответ. Он работает отлично! - person Firzen; 16.04.2020
comment
Действительно ценный ответ, работает хорошо, в отличие от самого getGlobalVisibleRect. - person Bitlejuce Do; 30.04.2020
comment
не используйте пересечение, если вы хотите просто проверить пересечение. Вместо этого используйте пересечения. Используйте пересечение, только если вы хотите записать пересечение - person Prakash; 08.12.2020

int[] location = new int[2];
view.getLocationOnScreen(location);

or

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

Теперь используйте это местоположение или прямоугольник, чтобы проверить, находится ли он в ваших видимых границах или нет. Если это просто весь экран, сверьтесь с getResources().getDisplayMetrics().

Как указал Antek в комментариях ниже, представление может по-прежнему исчезать или быть невидимым, а возвращаемые здесь значения сообщают, где оно было нарисовано в последний раз. Таким образом, сочетание приведенного выше условия, связанного с границами, с view.isShown() или view.getVisibility() == VISIBLE должно позаботиться об этом.

person AA_PV    schedule 17.01.2017
comment
это не работает при переключении видимости - если ваш вид изначально был видимым, он сохранит свои видимые прямоугольные размеры. - person Antek; 18.07.2017
comment
Вы также можете добавить проверку видимости представления. - person AA_PV; 18.07.2017
comment
что ты имеешь в виду? Представление теперь имеет visibility = GONE (я только что переключил его, у него было visibility = VISIBLE), но видимый прямоугольник остается таким, каким он был при создании представления. Проверять не надо, так как я сам поставил в одном месте в коде. - person Antek; 18.07.2017
comment
Я имел в виду, что в зависимости от намерения вы можете добавить проверку для view.getVisibility() == VISIBLE вместе с позицией, возвращаемой на экране. Для вопроса на самом деле имеет смысл добавить его, я отредактирую ответ. Спасибо - person AA_PV; 18.07.2017
comment
@Antek Было бы интересно проверить это, если вы работаете над этим - что происходит, когда вид рисуется, затем делается GONE, а затем больше никогда не рисуется? Я предполагал, что GONE обновит местоположение, но если это не так, стоит проверить, не останемся ли мы с устаревшим местоположением в будущем. Спасибо! - person AA_PV; 18.07.2017
comment
изменение видимости на GONE на самом деле не меняет местоположение - для моего конкретного случая это 0,0 в любом случае (группа полноэкранного просмотра) - person Antek; 18.07.2017
comment
и на самом деле я просто подожду немного (100 мс?) в фоновом потоке, потому что я заметил, что мне не нужно явно проверять рисуемое представление или нет - проблема (скорее всего) вызвана вызовом этого фрагмента код много раз в секунду из другого места. - person Antek; 18.07.2017
comment
0,0! В любом случае мое редактирование относится к невидимому виду: P - person AA_PV; 19.07.2017
comment
ну, я так понимаю, что под location они имели в виду левый верхний угол вида (который может иметь некоторые размеры) - поэтому любой вид, расположенный там, независимо от размера, будет иметь такое расположение. - person Antek; 19.07.2017
comment
да... попробуйте вместо этого получить видимый Rect в вашем случае - person AA_PV; 23.07.2017
comment
ты имеешь в виду boundingBox? - person Antek; 25.07.2017

Ответ zegee29 очень помогает. Хотя я хотел бы предложить также использовать результат view.getGlobalVisibleRect(actualPosition), потому что в некоторых случаях Rect.intersects() возвращает true, когда элемент вообще не виден, поэтому результирующий код:

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)
}

Или вы можете просто результат getGlobalVisibleRect(actualPosition)

person Диана Ганеева    schedule 01.04.2021

пытаться

if(view.isShown()) {
    // Visible
} else { 
    // Invisible
}
person Rohit Suthar    schedule 03.06.2016
comment
Это будет верно, если, например, есть наложение, закрывающее View, поэтому ненадежный и не правильный ответ. - person r3flss ExlUtr; 05.12.2016
comment
Это неправильно. isShown() возвращает свойство видимости представления. - person The Hungry Androider; 13.07.2017
comment
Почему у этого есть несколько голосов? Это неправильные люди! - person hasen; 15.07.2017

общественное логическое значение checkVisiblity (представление вида) {

если (view.isShown()) вернуть истину; иначе вернуть ложь;

}

person Jaydev Bharadwaj    schedule 02.05.2015

Функция View.getVisibility() может иметь следующие значения:

  • View.VISIBLE (0): вид виден.

  • View.INVISIBLE (1): представление невидимо, но оно по-прежнему занимает место для макета.

  • View.GONE (2): представление исчезло. Полностью скрыт, как будто вид не добавлялся

Вы можете увидеть ссылку ниже для получения дополнительной информации. Как можно Я проверяю, отображается ли представление в Android?

person secretlm    schedule 26.12.2012
comment
Почему бы не отдать должное оригинальному ответу? stackoverflow.com/a/3791698/562935 - person tidbeck; 25.06.2013
comment
@tidbeck этот ответ совершенно неверен! он хочет знать, виден вид прямо сейчас на экране или нет! Атрибут видимости всегда возвращает видимость, если вы его не измените. этот атрибут не связан с прокруткой, он изменяется только программистом. - person Siavash Abdoli; 26.01.2016
comment
Кстати, константы для видимого, невидимого и ушедшего — 0,4 и 8 соответственно. - person GAMA; 04.03.2016