Android: usando MotionEvent para arrastrar y soltar el posicionamiento de vistas en un grupo de vistas personalizado

Tengo problemas para posicionar elementos de vista en un grupo de vistas personalizado que he creado, específicamente en situaciones de arrastrar y soltar. Tengo como objetivo Android 2.2 y versiones posteriores, por lo que no puedo usar la API de arrastrar y soltar que surgió en Android 3.

Mi ViewGroup personalizado se llama "NodeGrid" y extiende "RelativeLayout". Su método onLayout se anula tal que se ve así:

@Override protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) { //pxConversion is a multiplier to convert 1 dip to x pixels. //We will use it to convert dip units into px units. Resources r = getResources(); float pxConversion = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, r.getDisplayMetrics()); //Layout the children of this viewgroup int childCount = this.getChildCount(); for (int i = 0; i < childCount; i++) { NodeView view = (NodeView) this.getChildAt(i); if (view.DataContext != null) { int left = (int) (view.DataContext.get_left() * pxConversion); int top = (int) (view.DataContext.get_top() * pxConversion); int right = left + (int) (view.DataContext.get_width() * pxConversion); int bottom = top + (int) (view.DataContext.get_height() * pxConversion); view.layout(left, top, right, bottom); } } } 

Los hijos de "NodeGrid" son del tipo "NodeView" (como se puede ver en el código anterior). NodeView es simplemente una clase de vista personalizada que he creado. Contiene un miembro denominado "DataContext" que es una clase de modelo de vista que contiene algunos getters / setters con información de posición sobre la instancia de NodeView en NodeGrid.

Mi clase "NodeView" captura eventos táctiles por el usuario, por lo que el usuario puede simplemente arrastrar y soltar un nodo en cualquier lugar de la cuadrícula. El controlador de eventos tiene este aspecto:

 @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { isBeingDragged = true; } else if (event.getAction() == MotionEvent.ACTION_UP) { isBeingDragged = false; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (DataContext != null && isBeingDragged) { float xPosition = event.getRawX(); float yPosition = event.getRawY(); DataContext.set_left(xPosition); DataContext.set_top(yPosition); this.requestLayout(); } } return true; } 

Mi problema es que la vista que se está arrastrando no se coloca como yo lo esperaría en mi "NodeGrid". Parece que la posición del eje x es correcta al arrastrarla, pero la posición del eje y está desplazada por una cantidad constante de píxeles en cualquier momento. ¿Qué estaría causando esto? He intentado usar los métodos getX () y getY () en lugar de getRawX () y getRawY (), pero eso sólo hace que sea peor.

No estaba seguro de si getRawX () y getRawY () estaban retornando unidades px o unidades de inmersión a mí, por lo que esperaba que me estuviera devolviendo unidades px, intenté convertirlas en unidades dip antes de asignar los nuevos valores xey para El nodo, pero que sólo disminuyó el desplazamiento, no lo eliminó.

¿Qué podría estar causando la diferencia en donde estoy tocando y dónde se está colocando el nodo?

One Solution collect form web for “Android: usando MotionEvent para arrastrar y soltar el posicionamiento de vistas en un grupo de vistas personalizado”

Muy sorprendido de que al parecer nadie más ha encontrado este tipo de situación …

Después de algunas investigaciones, he sido parcialmente capaz de resolver el problema.

La razón por la que getRawX () y getRawY () no funciona es porque funcionan fuera de la posición absoluta de la pantalla sin tener en cuenta nada en la pantalla que no sea parte de su aplicación (como el menú de Android que está constantemente en la parte superior de la pantalla A menos que esté en modo de pantalla completa). El uso de estas coordenadas parecía hackish, especialmente sin ninguna manera aparente de justificarlos y convertirlos a "mi aplicación" coordenadas.

GetX () y getY () parecen ser relativos al objeto que se toca en la medida de lo que puedo decir. Al tener esto en cuenta, cambié el código en onTouchEvent para que lea:

 float xPosition = event.getX(); float yPosition = event.getY(); DataContext.set_left(DataContext.get_left() + xPosition); DataContext.set_top(DataContext.get_top() + yPosition); this.requestLayout(); 

Esto definitivamente ayuda … pero todavía no parece ser una solución perfecta. En general, hace que el objeto de vista para arrastrar junto con el cursor del ratón / dedo, pero es muy nervioso, y todavía hay momentos en que puede llegar whacky y salir de la pantalla.

Entonces pensé que tal vez es porque no estoy incorporando "coordenadas históricas" en el método. Intenté incorporar coordenadas históricas en el método poniendo este código inmediatamente antes del código que acabo de mostrar arriba:

 int historySize = event.getHistorySize(); for (int i = 0; i < historySize; i++) { float xPosition = event.getHistoricalX(i); float yPosition = event.getHistoricalY(i); DataContext.set_left(DataContext.get_left() + xPosition); DataContext.set_top(DataContext.get_top() + yPosition); this.requestLayout(); } 

Por desgracia … esto realmente lo hace peor, así que no estoy usando las coordenadas históricas correctamente o no deben ser utilizados en absoluto. Voy a publicar otra pregunta con respecto a este asunto, pero esto debería bastar como una respuesta parcial a mi pregunta anterior.

  • Android: obtener Viewgroup de la vista?
  • Estado de envío de los controles compuestos
  • NullPointerException: Intento de leer del campo 'int android.view.View.mViewFlags'
  • Android View y ViewGroup
  • ¿Por qué ir para el diseño de restricciones ya que ya tenemos Disposición relativa?
  • Android StackOverflowError en ViewGroup.resetResolvedTextDirection
  • ¿Cuál es la estructura de diseño típica de una actividad de configuración de Android?
  • Evento de inflado de acabado de ViewGroup
  • Establecer GestureDetector en todas las vistas de niños
  • Escala de diseño relativo personalizado?
  • Inflación del diseño XML en un grupo de vistas personalizado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.