¿Cómo puedo establecer dinámicamente la posición de la vista en Android?

102

¿Cómo puedo cambiar la posición de la vista a través del código? Como cambiar su posición X, Y. ¿Es posible?

Arun Badole
fuente

Respuestas:

117

Para cualquier cosa por debajo de Honeycomb (API nivel 11) tendrá que usar setLayoutParams(...).

Si puede limitar su apoyo a nido de abeja y hasta puede utilizar el setX(...), setY(...), setLeft(...), setTop(...), etc.

Dave perecedero
fuente
40
de los documentos de setTop () developer.android.com/reference/android/view/… : sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.- así que tal vez esa no sea una buena idea;)
katzenhut
47

Sí, puede establecer dinámicamente la posición de la vista en Android. Del mismo modo tiene una ImageViewen LinearLayoutsu xml file.So puede ajustar su posición a través LayoutParams.Pero asegúrese de tomar LayoutParamssegún la disposición tomada en su xml file.There son diferentes LayoutParamssegún la disposición tomada.

Aquí está el código para configurar:

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

Espero que le sea de ayuda establecer la posición.

AkashG
fuente
15
también tenga en cuenta que debe importar android.widget.LinearLayout.LayoutParams; porque el valor predeterminado es LayoutParams de ViewGroup
David T.
Esto no parece funcionar en Android 8+. ¿Ha enfrentado un problema similar?
MyFlashLab
Alguna idea de por qué los diseñadores de Andriod se toman tantas molestias para evitar que los jugadores usen X, Y para posicionar las cosas. Eventualmente, todo tiene que dibujarse de esa manera. Esto sugiere que Android está siendo diseñado por personas que no pueden codificar.
Paul McCarthy
33

Ya existen diferentes respuestas válidas, pero ninguna parece sugerir correctamente qué método (s) usar en cuyo caso, excepto por las restricciones de nivel de API correspondientes:

  • Si puede esperar un ciclo de diseño y el grupo de vista principal admite MarginLayoutParams(o una subclase), configure marginLeft/ en marginTopconsecuencia.

  • Si necesita cambiar la posición de forma inmediata y persistente (por ejemplo, para un ancla PopupMenu), llame adicionalmente layout(l, t, r, b)con las mismas coordenadas. Esto reemplaza lo que el sistema de diseño confirmará más adelante.

  • Para cambios inmediatos (temporales) (como animaciones), use setX()/ en su setY()lugar. En los casos en que el tamaño de los padres no depende de WRAP_CHILDREN, podría estar bien usar setX()/ setY()exclusivamente.

  • Nunca use setLeft()/ setRight()/ setBottom()/ setTop(), consulte a continuación.

Fondo : Los campos mLeft/ mTop/ mBottom/ mRightse completan desde los LayoutParams correspondientes en layout (). El sistema de diseño de vistas de Android llama al diseño de forma implícita y asincrónica. Por lo tanto, configurar MarginLayoutParamsparece ser la forma más segura y limpia de configurar la posición de forma permanente. Sin embargo, el retraso de diseño asincrónico puede ser un problema en algunos casos, por ejemplo, cuando se usa una Vista para representar un cursor, y se supone que debe ser reubicado y servir como un ancla de PopupMenu al mismo tiempo. En este caso, llamar layout()funcionó bien para mí.

Los problemas con setLeft()y setTop()son:

  • Llamarlos por sí solo no es suficiente; también debe llamar setRight()y setBottom()evitar estirar o reducir la vista.

  • La implementación de estos métodos parece relativamente compleja (= hacer un trabajo para tener en cuenta los cambios de tamaño de vista causados ​​por cada uno de ellos)

  • Parecen causar problemas extraños con los campos de entrada: el teclado numérico suave EditText a veces no permite dígitos

setX()y setY()trabajar fuera del sistema de diseño, y los valores correspondientes se tratan como un desplazamiento adicional a los valores de izquierda / arriba / abajo / derecha determinados por el sistema de diseño, cambiando la vista en consecuencia. Parece que se han agregado para animaciones (donde se requiere un efecto inmediato sin pasar por un ciclo de diseño).

Stefan Haustein
fuente
Hola Stefan. ¿Podría aconsejarme algunos libros o artículos en los que pueda entender cómo funciona el sistema de diseño de Android? Entiendo esa secuencia de llamadas de layout () onMeasure () onDraw (), pero quiero saber más detalles. Gracias de antemano
Sergey Brazhnik
Desafortunadamente, no puedo; la mejor y más definitiva referencia parece ser el código fuente real de Android O :)
Stefan Haustein
Utilizo setY para cambiar la vista, ¿cambia en el próximo ciclo de diseño, no es inmediato?
señal
¿Comó determinaste esto?
Stefan Haustein
Vale la pena señalar que marginLeftse puede configurar setLayoutParamscon un new FrameLayout.LayoutParams(width, height)en el que se establece elmarginLeft
lucidbrot
18

Hay una biblioteca llamada NineOldAndroids , que le permite usar la biblioteca de animación Honeycomb hasta la versión uno.

Esto significa que puede definir left, right, translationX / Y con una interfaz ligeramente diferente.

Así es como funciona:

ViewHelper.setTranslationX(view, 50f);

Simplemente use los métodos estáticos de la clase ViewHelper, pase la vista y el valor que desee establecer.

Ben
fuente
16

Recomendaría usar setTranslationXy setTranslationY. Recién estoy comenzando con esto, pero esta parece ser la forma más segura y preferida de mover una vista. Supongo que depende mucho de lo que intentes hacer exactamente, pero esto me funciona bien para la animación 2D.

Brianmearns
fuente
13

Puede intentar utilizar los siguientes métodos, si está utilizando HoneyComb Sdk (API nivel 11).

view.setX(float x);

El parámetro x es la posición x visual de esta vista.

view.setY(float y);

El parámetro y es la posición visual y de esta vista.

Espero que te sea de ayuda. :)

Arroz con pollo
fuente
4
Estoy trabajando en 2.2 Froyo y estos métodos no están disponibles en él.
Arun Badole
7

Para el apoyo a todos los niveles de la API se puede utilizar es la siguiente:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Orr
fuente
Porque quiere cambiar la posición y la solución anterior es mejor y no necesita animación
FireZenk
Además, la traducción puede hacer que la vista salga (parcialmente) de la pantalla
mewa
4

Establezca la posición izquierda de esta vista en relación con su padre:

view.setLeft(int leftPosition);

Establezca la posición correcta de esta vista en relación con su padre:

view.setRight(int rightPosition);

Establezca la posición superior de esta vista en relación con su padre:

view.setTop(int topPosition);

Establezca la posición inferior de esta vista en relación con su padre:

view.setBottom(int bottomPositon);

Los métodos anteriores se utilizan para establecer la posición de la vista relacionada con su padre.

Balaji.K
fuente
Lo sentimos Estos métodos no están disponibles. ¿Me pueden enviar algún código?
Arun Badole
4
"Este método está destinado a ser llamado por el sistema de diseño y generalmente no debería ser llamado de otra manera, porque la propiedad puede ser cambiada en cualquier momento por el diseño".
GDanger
4

Utilice LayoutParams. Si está utilizando un LinearLayout, debe importar android.widget.LinearLayout.LayoutParams, de lo contrario, importe la versión adecuada de LayoutParams para el diseño que está usando, o provocará una ClassCastException , entonces:

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

NB: Tenga en cuenta que también puede usar imageView.setLeft (int dim), PERO ESTO NO establecerá la posición del componente, solo establecerá la posición del borde izquierdo del componente, el resto permanecerá en la misma posición .

Alessandro Muzzi
fuente
Entonces, ¿cómo podemos mover la vista a una posición específica sin afectar la vista original?
james
No estoy seguro de haber entendido su problema porque si desea mover una vista, la cambiará por el hecho de que la está moviendo. De todos modos, si desea mover una vista sobre otra independientemente de ella, es posible que necesite una vista de FrameLayout que supere su diseño principal y luego, dentro de ella, puede colocar sus vistas independientes (obviamente, si desea que se mueva debajo de su vista principal, tienes que colocar el FrameLayout antes que el principal)
Alessandro Muzzi
3

Use RelativeLayout, coloque su vista en él, obtenga el RelativeLayout.LayoutParamsobjeto de su vista y establezca los márgenes que necesite. Entonces invoque requestLayout()su punto de vista. Esta es la única forma que conozco.

glodos
fuente
1

Descubrí que @Stefan Haustein se acerca mucho a mi experiencia, pero no estoy seguro al 100%. Mi sugerencia es:

  • setLeft()/ setRight()/ setBottom()/setTop() no funcionará a veces.
  • Si desea establecer una posición temporalmente (por ejemplo, para hacer una animación, no se ve afectada una jerarquía) cuando se agregó y se mostró la vista , simplemente use setX()/ en susetY() lugar. (Es posible que desee buscar más en la diferencia setLeft()ysetX() )
  • Y tenga en cuenta que X, Y parecen ser absolutos y fue compatible con AbsoluteLayout, que ahora está en desuso. Por lo tanto, cree que es probable que X, Y ya no sean compatibles. Y sí, lo es, pero solo en parte. Significa que si se agrega su vista, setX (), setY () funcionará perfectamente ; de lo contrario, cuando intente agregar una vista en el diseño del grupo de vistas (por ejemplo, FrameLayout, LinearLayout, RelativeLayout), debe establecer sus LayoutParams con marginLeft, marginTop en su lugar (setX (), setY () en este caso no funcionará a veces).
  • Establecer la posición de la vista por marginLeft y marginTop es un proceso no sincronizado . Por lo que necesita un poco de tiempo para actualizar la jerarquía . Si utiliza la vista inmediatamente después de establecer el margen , es posible que obtenga un valor incorrecto .
Nguyen Tan Dat
fuente
0

Una cosa a tener en cuenta con el posicionamiento es que cada vista tiene un índice relativo a su vista principal. Entonces, si tiene un diseño lineal con tres subvistas, cada una de las subvistas tendrá un índice: 0, 1, 2 en el caso anterior.

Esto le permite agregar una vista a la última posición (o al final) en una vista principal haciendo algo como esto:

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

Alternativamente, puede reemplazar una vista usando algo como lo siguiente:

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

parentView.addView(newView, childIndex);
Braden Holt
fuente