Подтвердить что ты не робот

Определите, есть ли представление на экране - Android

Я немного застрял в этом вопросе - в первую очередь, эта ссылка была полезной, однако я столкнулся с некоторой проблемой с видимостью:

Ссылка: Проверить видимость просмотра

У меня есть вид прокрутки (родительский) и ряд под-представлений (LinearLayoutTableLayout) и т.д. В XML файле (android:visibility="gone") есть несколько элементов, которые я установил View.GONE.

У меня есть простой код, чтобы определить, видно ли это или нет с помощью getVisibility(), но когда я установил элемент в View.VISIBLE и попытаюсь сразу getDrawingRect(), я получаю Rect с нулями по всей доске. Любой последующий щелчок получает правильные координаты.

Теперь это может быть связано с тем, что представление никогда не было нарисовано (как определено в XML), заставляя его не возвращать никакие координаты, но я устанавливаю View.VISIBLE, прежде чем пытаться определить видимость экрана. Может быть, мне нужно получить какой-то обратный вызов, скажем, onDraw()? или, возможно, установить видимость скрытых элементов в коде. Немного раздражает; (

Некоторые коды:

Rect scrollBounds = new Rect();
scroll.getHitRect(scrollBounds);

Rect viewBounds = new Rect();

if (view.getVisibility() == View.GONE) {
    view.setVisibility(View.VISBLE)


    viewBounds.getDrawingRect(viewBounds);
    if (!Rect.intersects(scrollBounds, viewBounds) {
        // do somthing
    } 
}

Область макетов следующим образом:

  • ScrollView
    • LinearLayout
      • TableLayout
        • Button
        • HiddenView

Конечно, очень вероятно, что я полностью об этом поменяю - в основном я просто хочу убедиться, что scrollview позиционирует себя так, чтобы вид, который стал видимым, можно увидеть в нем целиком.

Если какая-либо другая информация требуется, дайте мне знать!

4b9b3361

Ответ 1

Хорошо, так спасибо OceanLife за то, что указал мне в правильном направлении! Действительно, требуется обратный вызов, и ViewTreeObserver.OnGlobalLayoutListener() сделал трюк. Я закончил реализацию слушателя против моего класса фрагментов и поднял его там, где мне это нужно. Спасибо за предупреждение также в отношении множественных вызовов, я решил это с помощью метода removeOnGlobalLayoutListener() - работает прелесть.

код:

...

// vto initialised in my onCreateView() method

vto = getView().getViewTreeObserver();
vto.addOnGlobalLayoutListener(this);

...

@Override
    public void onGlobalLayout() {

        final int i[] = new int[2];
        final Rect scrollBounds = new Rect();

        sView.getHitRect(scrollBounds);
        tempView.getLocationOnScreen(i);

        if (i[1] >= scrollBounds.bottom) {
            sView.post(new Runnable() {
                @Override
                public void run() {
                    sView.smoothScrollTo(0, sView.getScrollY() + (i[1] - scrollBounds.bottom));
                }
            });
        }

        vto.removeOnGlobalLayoutListener(this);
    }

Просто нужно сделать очистку сейчас...

Ответ 2

Итак, если я правильно это читаю, проблема заключается в том, что вы хотите узнать размеры какого-либо представления в своем макете, чтобы узнать, есть ли у вас пересечение с родительским ScrollView.

То, что я думаю, что вы видите (как вы указали), является инструкцией для направления отправленного представления, а затем в каком-то гоночном состоянии рендеринг, разрешающий измерения для макета и фактический рендер, где объекты вида получают реальные размеры. Один из способов узнать, какие размеры, которые имеет вид на экране, - использовать дерево-прослушиватель макета. Мы используем этого наблюдателя для разрешения размеров экрана при использовании API графиков Google, для чего требуется определить ширину и высоту пикселя... что, конечно, на Android, вероятно, является самой большой проблемой для разработчиков. Итак, соблюдайте (каламбур);

final ViewTreeObserver vto = chart.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  /**
   * @see android.view.ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()
   */
  @SuppressWarnings("deprecation")
  @Override
  public void onGlobalLayout() {
    if (view.getVisibility() == View.GONE) {
      view.setVisibility(View.VISBLE)
      viewBounds.getDrawingRect(viewBounds);
      if (!Rect.intersects(scrollBounds, viewBounds) {
        // do something
      } 
    }
  }
});

Слово предупреждения onGlobalLayout будет вызываться несколько раз, когда рендеринг закрывается в конечном решении. Последний вызов - тот, который мы принимаем.

Это предоставит вам механизм для выполнения действий в нарисованном виде, например, получение ширины и высоты представления. Надеюсь, что это поможет тебе.

Кроме того: умные главы на площади спроектировали библиотеку FEST hamcrest, которая позволит вам написать тест для этого вместе с Robotium. Проверьте это.

Ответ 3

Я мог бы найти более простой способ проверить, отображается ли какая-то часть вида на экране (находится внутри области просмотра). "theView" - это представление, для которого мы хотим проверить, является ли оно частично (или полностью) видимым. Код Котлина:

 theView.viewTreeObserver.addOnGlobalLayoutListener {

            val visibleOnScreen = theView.getGlobalVisibleRect(Rect())
            if(visibleOnScreen)
            {
                // do something
            }
        }