2012-09-21 10 views
5

Tengo un ScrollView vertical (en realidad, un ScrollView personalizado, código debajo) dentro de un ViewFlipper. El ViewFlipper funciona bien a menos que deslice horizontalmente sobre ScrollView para pasar a la vista anterior/siguiente. ScrollView en sí funciona correctamente.No se puede obtener la aventura horizontal en un ScrollView dentro de un ViewFlipper para crear

Aquí está el diseño. El cuadro verde es ScrollView, que debe ser vertical.

enter image description here

Aquí está la ScrollView:

public class SCScrollView extends ScrollView { 

    private float xDistance, yDistance, lastX, lastY; 

    GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector()); 
    OnTouchListener gestureListener; 

    public SCScrollView(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     gestureListener = new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (gestureDetector.onTouchEvent(event)) { 
        return true; 
       } 
       return false; 
      }  
     }; 

    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     switch (ev.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       xDistance = yDistance = 0f; 
       lastX = ev.getX(); 
       lastY = ev.getY(); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       final float curX = ev.getX(); 
       final float curY = ev.getY(); 
       xDistance += Math.abs(curX - lastX); 
       yDistance += Math.abs(curY - lastY); 
       lastX = curX; 
       lastY = curY; 
       if(xDistance > yDistance) 
        return false; 
     } 

     return false; 
     //return super.onInterceptTouchEvent(ev); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     super.onTouchEvent(event); 
     return gestureDetector.onTouchEvent(event); 
    } 

    @Override 
    public boolean dispatchTouchEvent(MotionEvent ev){ 
     gestureDetector.onTouchEvent(ev); 
     super.dispatchTouchEvent(ev); 
     return true; 
    } 

    /** GestureDetector used to swipe between classes */ 
    class MyGestureDetector extends GestureDetector.SimpleOnGestureListener { 
     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float  velocityY) { 
      return false; 
     } 
    } 

} 

He estado tratando de basar la solución en el consejo aquí HorizontalScrollView within ScrollView Touch Handling y aquí Swipe/Fling tab-changing in conjunction with ScrollView? pero independientemente de lo que vuelvo de las devoluciones de llamada, no puedo conseguir el ViewFlipper para ver la aventura en ScrollView y, francamente, me estoy perdiendo en la cadena de oyentes táctiles y gestuales.

¿Alguna idea?

Gracias

+0

Ha intentado añadir un OnTouchListener a la ScrollView del ViewFlipper, tal vez usted puede conseguir de esta manera los TouchEvents necesarios? – Artjom

+0

Hola Artjom. Sí, eso es lo que intenté primero, pero parece que ScrollView está consumiendo la aventura horicental, aunque no es necesario. Es por eso que estoy intentando anular el ScrollView para poder detener el consumo y subirlo al ViewFlipper principal, pero hasta ahora no es bueno :( – Simon

Respuesta

6

igual que en el documentado dijeron

http://developer.android.com/reference/android/widget/ScrollView.html

ScrollView sólo es compatible con el desplazamiento vertical. Para desplazamiento horizontal, use HorizontalScrollView.

Por lo tanto, tengo que preguntar por qué realmente desea utilizar su scrollview personalizado?

Si sólo va a ser capaz de desplazarse, es posible que no hay necesidad de utilizar

única RelativeLayout.scrollBy (x, y); es suficiente

Se podría buscar en este enlace

Scrollview vertical and horizontal in android

EDITAR

Ok, por lo que necesita para hacer el gesto detectar la aventura sobre el ScrollView.

Se podría hacer en su actividad sin la fabricación de encargo ScrollView también

primero, es necesario

implements OnGestureListener, OnTouchListener, GestureDetector.OnDoubleTapListener 

y en la clase de crear gestureDetector

gd = new GestureDetector(this); 

y su objeto ScrollView, acaba de declarar

sv.setOnTouchListener(this); 

a continuación, en el método sustituto onTouch

@Override 
public boolean onTouch(View v, MotionEvent event) { 
     onTouchEvent(event); // throw to onTouchEvent 

    return false; 
} 

y en el método onTouchEvent anulación

@Override 
public boolean onTouchEvent(MotionEvent me) 
{ 
    return gd.onTouchEvent(me); // gd = gesturedetector 
} 

ahora anular su método onFling como esto

private static final int SWIPE_MIN_DISTANCE = 120; 
private static final int SWIPE_THRESHOLD_VELOCITY = 200; 

@Override 
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
     float velocityY) { 

    if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
     // "Left Swipe" 
     vf.showPrevious(); // vf = ViewFlipper 

    } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
     // "Right Swipe" 
     vf.showNext(); 
    } 

    return false; 
} 

y esto es el todo código

clase ViewFlipperActivity

import android.os.Bundle; 
import android.app.Activity; 
import android.view.GestureDetector; 
import android.view.GestureDetector.OnGestureListener; 
import android.view.View.OnTouchListener; 
import android.view.MotionEvent; 
import android.view.View; 
import android.webkit.WebSettings; 
import android.webkit.WebView; 
import android.widget.HorizontalScrollView; 
import android.widget.ScrollView; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.widget.ViewFlipper; 

public class ViewFlipperActivity extends Activity implements OnGestureListener, OnTouchListener, GestureDetector.OnDoubleTapListener 
{ 

    TextView tv; 
    GestureDetector gd; 
    ScrollView sv; 
    ViewFlipper vf; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     gd = new GestureDetector(this); 

     setContentView(R.layout.activity_viewflipper); 

     tv = (TextView)findViewById(R.id.textView1); 
     sv = (ScrollView)findViewById(R.id.scrollView1); 
     vf = (ViewFlipper)findViewById(R.id.viewFlipper1); 

     sv.setOnTouchListener(this); 

    } 

    @Override 
    public boolean onDoubleTap(MotionEvent arg0) { 
     tv.setText("double tap"); 
     return false; 
    } 

    @Override 
    public boolean onDoubleTapEvent(MotionEvent arg0) { 
     tv.setText("double tap event"); 
     return false; 
    } 

    @Override 
    public boolean onSingleTapConfirmed(MotionEvent arg0) { 
     tv.setText("single tap confirm"); 
     return false; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent me) 
    { 
     return gd.onTouchEvent(me); 
    } 

    @Override 
    public boolean onDown(MotionEvent arg0) { 
     tv.setText("down"); 
     return false; 
    } 

    private static final int SWIPE_MIN_DISTANCE = 120; 
    private static final int SWIPE_THRESHOLD_VELOCITY = 200; 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
      float velocityY) { 

     if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
      tv.setText("Left Swipe"); 
      vf.showPrevious(); 

     } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
      tv.setText("Right Swipe"); 
      vf.showNext(); 
     } 

     return false; 
    } 

    @Override 
    public void onLongPress(MotionEvent arg0) { 
     tv.setText("long press"); 

    } 

    @Override 
    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, 
      float arg3) { 
     tv.setText("scroll"); 
     return false; 
    } 

    @Override 
    public void onShowPress(MotionEvent arg0) { 
     tv.setText("show press"); 
    } 


    @Override 
    public boolean onSingleTapUp(MotionEvent arg0) { 
     tv.setText("single tab up"); 
     return false; 
    } 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     onTouchEvent(event); 

     return false; 
    } 
} 

y activity_viewflipper.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" 
     android:text="TextView" /> 

    <ViewFlipper 
     android:id="@+id/viewFlipper1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:layout_below="@+id/textView1" > 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" > 

      <ScrollView 
       android:id="@+id/scrollView1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_above="@+id/textView3" 
       android:layout_alignParentLeft="true" 
       android:layout_alignParentTop="true" 
       android:layout_marginLeft="28dp" 
       android:layout_marginTop="63dp" 
       android:layout_toLeftOf="@+id/textView2" > 

       <ImageView 
        android:id="@+id/imageView1" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:scaleType="matrix" 
        android:src="@drawable/thailandmap" /> 

      </ScrollView> 

      <TextView 
       android:id="@+id/textView2" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_alignParentRight="true" 
       android:layout_alignTop="@+id/scrollView1" 
       android:layout_marginRight="30dp" 
       android:text="TextView" /> 

      <TextView 
       android:id="@+id/textView3" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_alignParentBottom="true" 
       android:layout_alignRight="@+id/scrollView1" 
       android:layout_marginBottom="250dp" 
       android:layout_marginRight="29dp" 
       android:text="TextView" /> 

     </RelativeLayout> 

     <ImageView 
      android:id="@+id/imageView2" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:scaleType="matrix" 
      android:src="@drawable/thwriting" /> 

    </ViewFlipper> 

</RelativeLayout> 
+0

Hola y gracias por tu respuesta. No estoy tratando de obtener un ScrollView horizantal. Intento que ViewFlipper reconozca el deslizamiento horizontal en ScrollView, que debería ir a la vista anterior o siguiente. He editado la pregunta para que sea (con suerte) más clara. – Simon

+0

OK, mira mi respuesta editada. Lo probé y es su trabajo. –

+0

Gracias, hombre. Intentaré esto mañana y volveré ... – Simon

Cuestiones relacionadas