Ответ 1
Используйте View.getLocationOnScreen()
и/или getLocationInWindow()
.
Я пытаюсь получить абсолютные пиксельные координаты верхнего левого угла представления. Тем не менее, все методы, которые я могу найти, такие как 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()
, как показано выше, но это не помогло.
Используйте View.getLocationOnScreen()
и/или getLocationInWindow()
.
Сначала вы должны получить прямоугольник 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));
Надеюсь, это поможет
Принятый ответ фактически не сообщил, как получить местоположение, так что вот немного подробнее. Вы передаете массив 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
для прослушивания, когда макет сделан, и вы можете получить измеренные координаты. (См. этот ответ.)Использование глобального приемника макетов всегда хорошо работало для меня. Преимущество состоит в том, что он способен переделывать вещи, если макет изменен, например. если что-то установлено в 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);
}
После комментария Ромен Гай, вот как я его исправил. Надеюсь, это поможет любому, у кого также возникла эта проблема.
Я действительно пытался получить позиции взглядов, прежде чем они были выложены на экране, но совершенно не было очевидно, что это происходит. Эти строки были помещены после запуска кода инициализации, поэтому я предположил, что все готово. Однако этот код все еще находился в onCreate(); поэкспериментируя с Thread.sleep(), я обнаружил, что макет фактически не финализирован до тех пор, пока onCreate() полностью не завершит выполнение onResume(). Так, действительно, код пытался запустить до того, как макет закончил располагаться на экране. Добавив код в OnClickListener (или какой-либо другой Listener), были получены правильные значения, потому что его можно было запустить только после завершения компоновки.
Следующая строка была предложена в качестве редактирования сообщества:
используйте onWindowfocuschanged(boolean hasFocus)
Используйте этот код, чтобы найти точные корни 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);
Я добавил/вычитал некоторые значения для настройки моего представления. Пожалуйста, сделайте эти строки только после того, как весь вид завышен.
Моя утилита 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);