Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't get the horizontal fling on a ScrollView within a ViewFlipper to bubble up

Tags:

android

I have a vertical ScrollView (actually, a custom ScrollView, code below) within a ViewFlipper. The ViewFlipper works fine unless I swipe horizantally over the ScrollView to flip to the previous/next view. The ScrollView itself works correctly.

Here's the design. The green box is the ScrollView, which should be vertical.

enter image description here

Here's the 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;
       }
    }

 }

I've been trying to base the solution on the advice here HorizontalScrollView within ScrollView Touch Handling and here Swipe/Fling tab-changing in conjunction with ScrollView? but regardless of what I return from the callbacks, I cannot get the ViewFlipper to see the fling across the ScrollView and frankly, I'm getting lost in the chain of touch and gesture listeners.

Any thoughts?

Thanks

like image 820
Simon Avatar asked Sep 21 '12 10:09

Simon


1 Answers

As in the documented said

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

ScrollView only supports vertical scrolling. For horizontal scrolling, use HorizontalScrollView.

So, I need to ask why did you really want to use your custom scrollview?

If you only intend to be able to scroll, you might no need to use it

only RelativeLayout.scrollBy(x,y); is enough

You could look at this link

Scrollview vertical and horizontal in android

EDIT

Ok, So you need to make the gesture detect the fling over the ScrollView.

You could make it in your Activity without making custom ScrollView also

first, you need to

implements OnGestureListener, OnTouchListener, GestureDetector.OnDoubleTapListener

and in your class create gestureDetector

gd = new GestureDetector(this);

and your ScrollView object, just declared

sv.setOnTouchListener(this);

then, in override onTouch method

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

    return false;
}

and in override onTouchEvent method

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

now override your onFling method like this

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;
}

and this is the whole code

ViewFlipperActivity class

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;
    }
}

and 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>
like image 150
Sruit A.Suk Avatar answered Nov 15 '22 00:11

Sruit A.Suk