Как я могу динамически установить положение просмотра в Android?

Как я могу изменить позицию просмотра кода? Как изменение его X, Y позиции. Является ли это возможным?

13 ответов

Решение

Для всего, что ниже Сота (API уровня 11), вам придется использовать setLayoutParams(...),

Если вы можете ограничить вашу поддержку Honeycomb и выше, вы можете использовать setX(...), setY(...), setLeft(...), setTop(...), так далее.

Да, вы можете динамически устанавливать положение просмотра в Android. Точно так же у вас есть ImageView в LinearLayout вашего XML-файла. Таким образом, вы можете установить его положение через LayoutParams. Но обязательно принять LayoutParams в соответствии с макетом, принятым в вашем XML-файле. LayoutParams по макету принято.

Вот код для установки:

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);

Я надеюсь, что вам будет полезно установить позицию.

Уже есть разные действительные ответы, но, похоже, ни один из них не дает правильного представления о том, какой метод (ы) использовать в каком случае, за исключением соответствующих ограничений уровня API:

  • Если вы можете ждать цикла макета и родительская группа представления поддерживает MarginLayoutParams (или подкласс), установите marginLeft / marginTop соответственно.

  • Если вам необходимо изменить позицию немедленно и постоянно (например, для привязки PopupMenu), дополнительно позвоните layout(l, t, r, b) с такими же координатами. Это прерывает то, что система макета подтвердит позже.

  • Для немедленных (временных) изменений (например, анимации) используйте setX() / setY() вместо. В случаях, когда размер родительского элемента не зависит от WRAP_CHILDREN, может быть целесообразно использовать setX() / setY() исключительно.

  • Никогда не используйте setLeft() / setRight() / setBottom() / setTop(), увидеть ниже.

Фон: mLeft / mTop / mBottom / mRight поля заполняются из соответствующих LayoutParams в layout(). Макет вызывается неявно и асинхронно системой макетов представления Android. Таким образом, установка MarginLayoutParams кажется, самый безопасный и чистый способ установить положение навсегда. Однако асинхронная задержка компоновки может быть проблемой в некоторых случаях, например, при использовании View для визуализации курсора, и он должен быть перемещен и одновременно служить якорем PopupMenu. В этом случае звонит layout() работал нормально для меня.

Проблемы с setLeft() а также setTop() являются:

  • Одного их вызова недостаточно - нужно также позвонить setRight() а также setBottom() чтобы избежать растяжения или сжатия зрения.

  • Реализация этих методов выглядит относительно сложной (= выполнение некоторой работы для учета изменений размера представления, вызванных каждым из них)

  • Кажется, они вызывают странные проблемы с полями ввода: мягкая цифровая клавиатура EditText иногда не позволяет вводить цифры

setX() а также setY() работать вне системы макетов, и соответствующие значения обрабатываются как дополнительное смещение к левым / верхним / нижним / правым значениям, определенным системой макетов, соответственно смещая вид. Похоже, они были добавлены для анимации (где требуется немедленный эффект без прохождения цикла макета).

Существует библиотека под названием NineOldAndroids, которая позволяет вам использовать библиотеку анимации Honeycomb вплоть до первой версии.

Это означает, что вы можете определить left, right, translationX/Y с немного другим интерфейсом.

Вот как это работает:

ViewHelper.setTranslationX(view, 50f);

Вы просто используете статические методы из класса ViewHelper, передаете представление и любое значение, которое хотите установить.

Я бы порекомендовал использовать setTranslationX а также setTranslationY, Я только начинаю с этого, но это, кажется, самый безопасный и предпочтительный способ перемещения вида. Я думаю, это во многом зависит от того, что именно вы пытаетесь сделать, но это хорошо работает для меня для 2D-анимации.

Вы можете попробовать использовать следующие методы, если вы используете HoneyComb Sdk(уровень API 11).

view.setX(float x);

Параметр x - это визуальная позиция x этого вида.

view.setY(float y);

Параметр y - это визуальная позиция y этого вида.

Я надеюсь, что это будет полезно для вас.:)

Для поддержки всех уровней API вы можете использовать его следующим образом:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);

Установите левую позицию этого представления относительно его родителя:

view.setLeft(int leftPosition);

Установите правильную позицию этого представления относительно его родителя:

view.setRight(int rightPosition);

Установите верхнюю позицию этого представления относительно его родителя:

view.setTop(int topPosition);

Установите нижнюю позицию этого представления относительно его родителя:

view.setBottom(int bottomPositon);

Вышеуказанные методы используются для установки позиции представления, связанной с его родителем.

Используйте LayoutParams. Если вы используете LinearLayout, вам нужно импортировать android.widget.LinearLayout.LayoutParams, иначе импортировать правильную версию LayoutParams для используемого вами макета, иначе это вызовет исключение ClassCastException, а затем:

LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);

Примечание: обратите внимание, что вы также можете использовать imageView.setLeft(int dim), НО ЭТО НЕ БУДЕТ устанавливать позицию компонента, он будет устанавливать только положение левой границы компонента, остальные останутся на той же позиции,

Использование RelativeLayoutПоместите свой взгляд в это, получите RelativeLayout.LayoutParams Объект с вашей точки зрения и установите поля, как вам нужно. Тогда позвони requestLayout() на ваш взгляд. Это единственный способ, которым я знаю.

В Котлине вы можете сделать это, как показано ниже;

      view
    .animate()
    .x(50f)
    .y(100f)
    .duration = 500L

Я обнаружил, что @Stefan Haustein очень близок к моему опыту, но не уверен на 100%. Мое предложение:

  • setLeft() / setRight() / setBottom() / setTop() не будет работать иногда
  • Если вы хотите временно установить позицию (например, для анимации, не затрагивая иерархию), когда представление было добавлено и показано, просто используйте setX() / setY() вместо. (Возможно, вы хотите искать больше в разнице setLeft() а также setX())
  • И обратите внимание, что X, Y кажутся абсолютными, и это было поддержано AbsoluteLayout, который сейчас устарел. Таким образом, вы чувствуете, что X, Y, скорее всего, больше не поддерживается. И да, но только частично. Это означает, что если ваше представление добавлено, setX(), setY() будут работать отлично; в противном случае, когда вы пытаетесь добавить представление в макет группы представлений (например, FrameLayout, LinearLayout, RelativeLayout), вы должны установить его LayoutParams с помощью marginLeft, marginTop (setX(), setY() в этом случае иногда не будут работать).
  • Установка позиции представления с помощью marginLeft и marginTop является несинхронизированным процессом. Поэтому для обновления иерархии требуется немного времени. Если вы используете вид сразу после установки для него поля, вы можете получить неправильное значение.

При позиционировании следует помнить о том, что каждое представление имеет индекс относительно родительского представления. Итак, если у вас линейный макет с тремя вложенными представлениями, каждое из них будет иметь индекс: 0, 1, 2 в приведенном выше случае.

Это позволяет вам добавить представление в последнюю позицию (или конец) в родительском представлении, выполнив что-то вроде этого:

int childCount = parent.getChildCount();
parentView.addView(newView, childCount);

В качестве альтернативы вы можете заменить представление, используя что-то вроде следующего:

int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);

parentView.addView(newView, childIndex);
Другие вопросы по тегам