Определите, есть ли представление на экране - Android
Я немного застрял в этом вопросе - в первую очередь, эта ссылка была полезной, однако я столкнулся с некоторой проблемой с видимостью:
Ссылка: Проверить видимость просмотра
У меня есть вид прокрутки (родительский) и ряд под-представлений (LinearLayout
→ TableLayout
) и т.д. В 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 позиционирует себя так, чтобы вид, который стал видимым, можно увидеть в нем целиком.
Если какая-либо другая информация требуется, дайте мне знать!
Ответы
Ответ 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
}
}