Как получить абсолютные координаты вида

Я пытаюсь получить абсолютные пиксельные координаты верхнего левого угла представления. Тем не менее, все методы, которые я могу найти, такие как 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 (array [] array), содержащийся в TableLayout. Ячейки [0] - верхний левый ImageView, и я выбрал ячейки [4], поскольку он где-то посередине, и определенно не должен иметь координат (0,0).

Код, показанный выше, все равно дает мне все 0s в журналах, что я действительно не понимаю, потому что различные кусочки головоломки отображаются правильно. (Я попробовал public int для tableLayoutCorners и видимость по умолчанию, оба дали тот же результат.)

Я не знаю, является ли это значительным, но ImageView изначально не заданы. Размер ImageView определяется во время инициализации автоматически с помощью представления, когда я даю ему изображение для отображения. Может ли это способствовать тому, что их значения равны 0, хотя этот код регистрации после того, как ему дали изображение и автоматически изменили размер? Чтобы потенциально справиться с этим, я добавил код tableLayout.requestLayout(), как показано выше, но это не помогло.

Ответ 1

Используйте View.getLocationOnScreen() и/или getLocationInWindow().

Ответ 2

Сначала вы должны получить прямоугольник localVisible вида

Например,

Rect rectf = new Rect();

//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);

//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);

Log.d("WIDTH        :", String.valueOf(rectf.width()));
Log.d("HEIGHT       :", String.valueOf(rectf.height()));
Log.d("left         :", String.valueOf(rectf.left));
Log.d("right        :", String.valueOf(rectf.right));
Log.d("top          :", String.valueOf(rectf.top));
Log.d("bottom       :", String.valueOf(rectf.bottom));

Надеюсь, это поможет

Ответ 3

Принятый ответ фактически не сообщил, как получить местоположение, так что вот немного подробнее. Вы передаете массив int длины 2, а значения заменяются координатами вида (x, y) (верхнего, левого угла).

int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

Примечания

  • Замена getLocationOnScreen с getLocationInWindow следует дайте те же результаты в большинстве случаев (см. этот ответ).
  • Вы получите (0,0), если вы вызовете этот метод в onCreate, потому что представление еще не выведено. Вы можете использовать ViewTreeObserver для прослушивания, когда макет сделан, и вы можете получить измеренные координаты. (См. этот ответ.)

Ответ 4

Использование глобального приемника макетов всегда хорошо работало для меня. Преимущество состоит в том, что он способен переделывать вещи, если макет изменен, например. если что-то установлено в View.GONE или дочерние представления добавлены/удалены.

public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null); 

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
       new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // measure your views here
          }
       }
     );

     setContentView(mainLayout);
 }

Ответ 5

После комментария Ромен Гай, вот как я его исправил. Надеюсь, это поможет любому, у кого также возникла эта проблема.

Я действительно пытался получить позиции взглядов, прежде чем они были выложены на экране, но совершенно не было очевидно, что это происходит. Эти строки были помещены после запуска кода инициализации, поэтому я предположил, что все готово. Однако этот код все еще находился в onCreate(); поэкспериментируя с Thread.sleep(), я обнаружил, что макет фактически не финализирован до тех пор, пока onCreate() полностью не завершит выполнение onResume(). Так, действительно, код пытался запустить до того, как макет закончил располагаться на экране. Добавив код в OnClickListener (или какой-либо другой Listener), были получены правильные значения, потому что его можно было запустить только после завершения компоновки.


Следующая строка была предложена в качестве редактирования сообщества:

используйте onWindowfocuschanged(boolean hasFocus)

Ответ 6

Используйте этот код, чтобы найти точные корни X и Y:

int[] array = new int[2];
ViewForWhichLocationIsToBeFound.getLocationOnScreen(array);
if (AppConstants.DEBUG)
    Log.d(AppConstants.TAG, "array  X = " + array[0] + ", Y = " + array[1]);
ViewWhichToBeMovedOnFoundLocation.setTranslationX(array[0] + 21);
ViewWhichToBeMovedOnFoundLocation.setTranslationY(array[1] - 165);

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

Ответ 7

Моя утилита utils для получения местоположения просмотра, она вернет объект Point с x value и y value

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

Использование

Point viewALocation = getLocationOnScreen(viewA);