Я пытаюсь получить абсолютные координаты пикселей экрана в верхнем левом углу представления. Тем не менее, все методы, которые я могу найти, такие как getLeft()
и getRight()
не работают, так как все они кажутся относительными к родителю представления, таким образом, дают мне 0
. Как правильно это сделать?
Если это поможет, это для игры «навести порядок». Я хочу, чтобы пользователь мог нарисовать прямоугольник, чтобы выбрать несколько частей. Мое предположение состоит в том , что самый простой способ сделать это, чтобы getRawX()
и getRawY()
из , MotionEvent
а затем сравнить эти значения с верхним левым углом расположения удерживающей части. Зная размер кусочков, я могу определить, сколько кусочков было выбрано. Я понимаю, что могу использовать getX()
и getY()
на MotionEvent
, но так как возвращает относительную позицию, что затрудняет определение, какие части были выбраны. (Не невозможно, я знаю, но это кажется излишне сложным).
Изменить: это код, который я использовал, чтобы попытаться получить размер контейнера хранения, в соответствии с одним из вопросов. TableLayout
это стол, который содержит все кусочки головоломки.
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
Изменить 2: Вот код, который я пробовал, следуя другим предложенным ответам.
public int[] tableLayoutCorners = new int[2];
(...)
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
+ ", " + corners.bottom);
cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);
Этот код был добавлен после завершения инициализации. Изображение было разделено на массив ImageViews (массив cell []), содержащийся в a TableLayout
. Ячейки [0] находятся в верхнем левом углу ImageView
, и я выбрал ячейки [4], так как они где-то посередине и, безусловно, не должны иметь координаты (0,0).
Код, показанный выше, все еще дает мне все 0 в журналах, которые я действительно не понимаю, потому что различные части головоломки отображаются правильно. (Я попробовал public int для tableLayoutCorners и видимости по умолчанию, оба дали одинаковый результат.)
Я не знаю, значимо ли это, но ImageView
изначально размер не указан. Размер ImageView
s определяется во время инициализации автоматически при просмотре, когда я даю ему изображение для отображения. Может ли это способствовать тому, что их значения будут равны 0, даже если этот код регистрации будет после того, как они получили изображение и автоматически изменили размеры сами? Чтобы потенциально противостоять этому, я добавил код, tableLayout.requestLayout()
как показано выше, но это не помогло.
источник
Принятый ответ на самом деле не говорит, как получить местоположение, поэтому здесь немного подробнее. Вы передаете
int
массив длины 2, и значения заменяются координатами представления (x, y) (верхнего левого угла).Ноты
getLocationOnScreen
наgetLocationInWindow
должна давать одинаковые результаты в большинстве случаев (см. Этот ответ ). Однако, если вы находитесь в меньшем окне, например, в диалоговом окне или на пользовательской клавиатуре, вам нужно будет выбрать, какое из них лучше соответствует вашим потребностям.(0,0)
если вызовете этот метод,onCreate
потому что представление еще не было выложено. Вы можете использоватьViewTreeObserver
для прослушивания, когда макет сделан, и вы можете получить измеренные координаты. (Смотрите этот ответ .)источник
Сначала вы должны получить локально видимый прямоугольник вида
Например:
Надеюсь, это поможет
источник
getGlobalVisibleRect()
для абсолютных координат.Использование глобального макета слушателя всегда хорошо работало для меня. Он имеет преимущество в том, что может перезаписывать вещи при изменении макета, например, если что-то установлено в View.GONE или добавляются / удаляются дочерние представления.
источник
setContentView()
вызвал проблему в специальномActivity
приложении в моем приложении! Это было диалоговое занятие (windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true
). Его основной план (аLinearLayout
) не имеет прямого потомка с определеннымlayout_width
(все они былиmatch_parent
илиwrap_content
).После комментария Ромена Гая вот как я это исправил. Надеюсь, это поможет кому-нибудь еще, у кого также была эта проблема.
Я действительно пытался выяснить положение представлений до того, как они были выложены на экран, но это не было очевидно, что происходило. Эти строки были размещены после запуска кода инициализации, поэтому я предположил, что все было готово. Тем не менее, этот код все еще был в onCreate (); Поэкспериментировав с Thread.sleep (), я обнаружил, что макет на самом деле не завершен до тех пор, пока onCreate () полностью не завершит выполнение onResume (). И действительно, код пытался выполнить до того, как макет был размещен на экране. При добавлении кода в OnClickListener (или некоторый другой Listener) были получены правильные значения, потому что он мог быть запущен только после завершения макета.
Строка ниже была предложена как правка сообщества:
пожалуйста, используйте
onWindowfocuschanged(boolean hasFocus)
источник
setContentView(R.layout.something)
, но они не были загружены визуально. У них нет размера или позиции. Это не произойдет, пока не завершится первый проход макета, что произойдет в какой-то момент в будущем (обычно после onResume ()).Первый путь:
В Kotlin мы можем создать простое расширение для просмотра:
И просто получить координаты:
Второй способ:
Второй способ более прост:
и просто получить абсолютное X
view.absX()
и Y поview.absY()
источник
val location = IntArray(2).apply(::getLocationOnScreen)
Моя утилита для определения местоположения, она возвращает
Point
объект сx value
иy value
С помощью
источник
Вы можете получить координаты вида используя
getLocationOnScreen()
илиgetLocationInWindow()
После этого
x
иy
должен быть верхний левый угол обзора. Если ваш корневой макет меньше экрана (как в диалоге), использованиеgetLocationInWindow
будет относиться к его контейнеру, а не ко всему экрану.Решение Java
Чтобы у представления был шанс обновить, запустите запрос местоположения после того, как новый макет представления был рассчитан с помощью
view.post
:~~
Kotlin Solution
Чтобы у представления был шанс обновить, запустите запрос местоположения после того, как новый макет представления был рассчитан с помощью
view.post
:Я рекомендую создать функцию расширения для обработки этого:
И если вам нужна надежность, также добавьте:
источник
Используйте этот код, чтобы найти точные X и Y кординаты:
Я добавил / вычел некоторые значения, чтобы скорректировать мой взгляд. Пожалуйста, делайте эти строки только после того, как весь вид был раздут.
источник
Получите и вид, и размер на экране
источник
Просто в дополнение к ответам выше, на вопрос, куда и когда вам следует позвонить
getLocationOnScreen
?Любая информация, относящаяся к любому представлению, которое вы хотите получить, будет доступна только после того, как представление было размещено на экране. Вы можете легко сделать это, поместив свой код, который зависит от создания представления внутри этого (view.post (Runnable)):
источник