滑动和正常滚动有问题

时间:2017-09-20 03:11:55

标签: android textview touch scrollview swipe

我的活动包含一个覆盖整个屏幕的ScrollView中的TextView集。 TextView中的内容通常是多个页面。

我正在尝试启用触摸控制,包括单击,双击,向左滑动,向右滑动和捏合,这些工作正常。 然而问题是用户难以向左或向右滑动而不小心向上或向下滚动ScrollView(因此取消了滑动检测)

这是我在TextView上使用的自定义OnTouchListener

public class OnSwipeTouchListener implements OnTouchListener {

private final GestureDetector gestureDetector;
private boolean mTapConsumed = false;
private int mTapsDetected = 0;
private boolean mEnableTap = true;

public OnSwipeTouchListener (Context ctx){
    gestureDetector = new GestureDetector(ctx, new GestureListener());
}

private double mPinchOriginalDistance = 0;
private float mPinchLastScale = 1.0f;               //scale change for current pinch action
private ScrollView mScrollView;

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

    mScrollView = (ScrollView) v.getParent();
    if(event.getPointerCount() == 2) {
        mScrollView.requestDisallowInterceptTouchEvent(true);
        mTapConsumed = true;
        mTapsDetected = 0;
        switch(event.getAction() & MotionEvent.ACTION_MASK){

            case MotionEvent.ACTION_POINTER_DOWN:
                //pinch mode
                float distx, disty;
                //Get the current distance
                distx = event.getX(0) - event.getX(1);
                disty = event.getY(0) - event.getY(1);
                mPinchOriginalDistance = Math.sqrt(distx * distx + disty * disty);
                break;

            case MotionEvent.ACTION_MOVE:
                //Get the current distance
                distx = event.getX(0) - event.getX(1);
                disty = event.getY(0) - event.getY(1);
                double distance = Math.sqrt(distx * distx + disty * disty);
                if(mPinchOriginalDistance == 0)
                    break;
                float scale = (float)(distance / mPinchOriginalDistance);
                mPinchLastScale = scale;
                onPinchScaleChange(scale);
                break;

            case MotionEvent.ACTION_POINTER_UP:
                onPinchFinal(mPinchLastScale);
                mPinchOriginalDistance = 0;
                mPinchLastScale = 1.0f;
                break;

            default:
                break;
        }
        return true;
    }
    else
        return gestureDetector.onTouchEvent(event);

}

private final class GestureListener extends SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 80;
    private static final int SWIPE_VELOCITY_THRESHOLD = 60;
    private final static int GESTURE_TAP_DELAY = 300;
    private final static int GESTURE_FLING_DELAY = 1000;


    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        if(!mEnableTap)
            return true;
        mTapConsumed = false;
        mTapsDetected++;
        if(mTapsDetected == 1)
            handler.postDelayed(checkTap, GESTURE_TAP_DELAY);
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        if(!mEnableTap)
            return true;
        mTapConsumed = false;
        mTapsDetected++;
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        mEnableTap = false;
        mTapConsumed = true;
        mTapsDetected = 0;
        handler.removeCallbacks(postFling);
        handler.postDelayed(postFling, GESTURE_FLING_DELAY);    //dont allow a tap to be registered for a certain time
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            flingData(diffX, diffY);
            if (Math.abs(diffX) > Math.abs(diffY)) {

                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                    result = true;
                }
            }

        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}

//Prevents a single tap being detected as well as a double tap    
private Handler handler = new Handler();
private Runnable checkTap = new Runnable() {

    public void run() {
        try {
            if(!mTapConsumed && mTapsDetected >= 1) {
                if(mTapsDetected > 1)
                    onTapDouble();
                else
                    onTapSingle();
                mTapsDetected = 0;
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

};

//Prevents a tap from being detected for a short duration after a fling has occurred
private Runnable postFling = new Runnable() {

    public void run() {
        try {
            mEnableTap = true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
};



public void onSwipeRight() {
}

public void onSwipeLeft() {
}

public void onPinchScaleChange(float scale) {
}

public void onPinchFinal(float scale) {
}

public void onTapSingle() {
}

public void onTapDouble() {
}

public void flingData(float diffX, float diffY)
{

}

}

要清楚。 上面的代码可以工作,但是用户很难激活左侧或右侧,因为ScrollView想要向上或向下滚动。 我需要一种方法让用户更容易左右滑动。 有什么想法吗?

1 个答案:

答案 0 :(得分:0)

事实证明,有时最简单的答案是最好的。 我将onTouchListener应用于scrollview而不是textview,这一切在世界上都很好。 :)