Desplazamiento vertical y horizontal en android

Estoy realmente cansado de buscar una solución para Scrollview vertical y horizontal.

Leí que no hay vistas / diseños en el marco que implementen esta función, pero necesito algo como esto:

Necesito definir un diseño dentro de otro, el diseño infantil debe implementar desplazamiento vertical / horizontal para mover.

Inicialmente implementé un código que movía el diseño píxel por píxel, pero creo que no es el camino correcto. Lo probé con ScrollView y Horizontal ScrollView, pero nada funciona como yo quiero, porque solo implementa el desplazamiento vertical u horizontal.

Canvas no es mi solución porque necesito adjuntar oyentes en elementos secundarios de alguien.

¿Que puedo hacer?

Mezclando algunas de las sugerencias anteriores, y fue capaz de obtener una buena solución:

Vista de desplazamiento personalizada:

package com.scrollable.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ScrollView; public class VScroll extends ScrollView { public VScroll(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public VScroll(Context context, AttributeSet attrs) { super(context, attrs); } public VScroll(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent ev) { return false; } } 

CustomScrollView personalizado:

 package com.scrollable.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.HorizontalScrollView; public class HScroll extends HorizontalScrollView { public HScroll(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public HScroll(Context context, AttributeSet attrs) { super(context, attrs); } public HScroll(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent ev) { return false; } } 

la actividad ScrollableImageActivity:

 package com.scrollable.view; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.widget.HorizontalScrollView; import android.widget.ScrollView; public class ScrollableImageActivity extends Activity { private float mx, my; private float curX, curY; private ScrollView vScroll; private HorizontalScrollView hScroll; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); vScroll = (ScrollView) findViewById(R.id.vScroll); hScroll = (HorizontalScrollView) findViewById(R.id.hScroll); } @Override public boolean onTouchEvent(MotionEvent event) { float curX, curY; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mx = event.getX(); my = event.getY(); break; case MotionEvent.ACTION_MOVE: curX = event.getX(); curY = event.getY(); vScroll.scrollBy((int) (mx - curX), (int) (my - curY)); hScroll.scrollBy((int) (mx - curX), (int) (my - curY)); mx = curX; my = curY; break; case MotionEvent.ACTION_UP: curX = event.getX(); curY = event.getY(); vScroll.scrollBy((int) (mx - curX), (int) (my - curY)); hScroll.scrollBy((int) (mx - curX), (int) (my - curY)); break; } return true; } } 

el diseño:

         

Dado que este parece ser el primer resultado de búsqueda en Google para “Android vertical + horizontal ScrollView”, pensé que debería agregar esto aquí. Matt Clark ha creado una vista personalizada basada en la fuente de Android, y parece funcionar perfectamente: Two Dimensional ScrollView

Tenga en cuenta que la clase en esa página tiene un error al calcular el ancho horizontal de la vista. Una corrección de Manuel Hilty está en los comentarios:

Solución: reemplace la statement en la línea 808 por lo siguiente:

 final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED); 

Editar: El enlace ya no funciona, pero aquí hay un enlace a una versión anterior del blogpost .

Encontré una mejor solución.

XML: (design.xml)

        

Código de Java:

 public class Example extends Activity { private RelativeLayout container; private int currentX; private int currentY; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.design); container = (RelativeLayout)findViewById(R.id.container); int top = 0; int left = 0; ImageView image1 = ... RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); container.addView(image1, layoutParams); ImageView image2 = ... left+= 100; RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); container.addView(image2, layoutParams); ImageView image3 = ... left= 0; top+= 100; RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); container.addView(image3, layoutParams); ImageView image4 = ... left+= 100; RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); container.addView(image4, layoutParams); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { currentX = (int) event.getRawX(); currentY = (int) event.getRawY(); break; } case MotionEvent.ACTION_MOVE: { int x2 = (int) event.getRawX(); int y2 = (int) event.getRawY(); container.scrollBy(currentX - x2 , currentY - y2); currentX = x2; currentY = y2; break; } case MotionEvent.ACTION_UP: { break; } } return true; } } 

¡Eso funciona!

Si desea cargar otro diseño o control, la estructura es la misma.

Lo uso y funciona bien:

        

El enlace fuente está aquí: Android-spa

Mi solución basada en la respuesta de Mahdi Hijazi , pero sin ninguna vista personalizada:

Diseño:

      

Código (onCreate / onCreateView):

  final HorizontalScrollView hScroll = (HorizontalScrollView) value.findViewById(R.id.scrollHorizontal); final ScrollView vScroll = (ScrollView) value.findViewById(R.id.scrollVertical); vScroll.setOnTouchListener(new View.OnTouchListener() { //inner scroll listener @Override public boolean onTouch(View v, MotionEvent event) { return false; } }); hScroll.setOnTouchListener(new View.OnTouchListener() { //outer scroll listener private float mx, my, curX, curY; private boolean started = false; @Override public boolean onTouch(View v, MotionEvent event) { curX = event.getX(); curY = event.getY(); int dx = (int) (mx - curX); int dy = (int) (my - curY); switch (event.getAction()) { case MotionEvent.ACTION_MOVE: if (started) { vScroll.scrollBy(0, dy); hScroll.scrollBy(dx, 0); } else { started = true; } mx = curX; my = curY; break; case MotionEvent.ACTION_UP: vScroll.scrollBy(0, dy); hScroll.scrollBy(dx, 0); started = false; break; } return true; } }); 

Puede cambiar el orden de las vistas de desplazamiento. Simplemente cambie su orden en el diseño y en el código. Y, obviamente, en lugar de WateverViewYouWant, coloca el diseño / las vistas que desea desplazar en ambas direcciones.

Opción n. ° 1: puede crear un nuevo diseño de interfaz de usuario que no requiera el desplazamiento horizontal y vertical simultáneo.

Opción n. ° 2: puede obtener el código fuente en ScrollView y HorizontalScrollView , aprender cómo el equipo principal de Android los implementó y crear su propia implementación BiDirectionalScrollView .

Opción n.º 3: puede deshacerse de las dependencias que requieren que use el sistema de widgets y dibujar directamente en el canvas.

Opción n. ° 4: si tropieza con una aplicación de código abierto que parece implementar lo que busca, mire para ver cómo lo hicieron.

Prueba esto

       

dado que el enlace Two Dimensional Scrollview está muerto, no pude obtenerlo, así que creé mi propio componente. Se encarga de arrojar y funciona correctamente para mí. La única restricción es que wrap_content podría no funcionar correctamente para ese componente.

https://gist.github.com/androidseb/9902093

Tengo una solución para tu problema. Puede verificar el código ScrollView, solo maneja el desplazamiento vertical e ignora el horizontal y lo modifica. Quería una vista como una vista web, modifiqué ScrollView y funcionó bien para mí. Pero esto puede no satisfacer tus necesidades.

Déjame saber para qué tipo de UI estás apuntando.

Saludos,

Ravi Pandit

Jugando con el código, puede poner un HorizontalScrollView en un ScrollView. De este modo, puede tener los dos métodos de desplazamiento en la misma vista.

Fuente: http://androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html

Espero que esto pueda ayudarte.