0

I have tried this several times but I can´t solve it. I have a ScrollView with several views, which are moved by an ObjectAnimator. When you pulse a button, the views are moved vertically during a given time. I do PLAY and PAUSE, but when I move the scroll using my finger, I am not able to know the number of pixels that the scroll has been moved.

I want to move the scroll with my finger, pulse Play, and I would like the scroll to start scrolling where I have put it, not from the beginning. I´ve tried this:

view.setOnTouchListener(new OnTouchListener() {
           @Override
           public boolean onTouch(View v, MotionEvent event) {
               //Choose which motion action has been performed
               switch(event.getAction())
               {
               case MotionEvent.ACTION_DOWN:
                   //Get X, Y coordinates from the ImageView
                   X = (int) event.getX();
                   Y = (int) event.getY();
                   startX = event.getRawX();
                   startY = event.getRawY();
                   break;
               case MotionEvent.ACTION_MOVE:
                  Z = (int) event.getX();
                   S = (int) event.getY();
                   K = (int) event.getRawX();
                   P = (int) event.getRawY();
                   V = (int) (event.getRawY() - startY);
                   break;
               case MotionEvent.ACTION_UP:
                   A = (int) event.getX();
                   E = (int) event.getY();
                   break;
               }
               return true;
           }

});

It does not give the coordinates when I raise my finger. How could I know the number of pixels moved when I move the scroll? It´s an Android aplication. Thanks in advance!

user3711263
  • 69
  • 1
  • 9
  • You are already taking the right approach, but what are all those variables? `S`, `K`, `P`, `V`, `A`, `E`, `Z`, `X`, `Y`? Why do you need them all? You just have to calculate the difference between the x and y coordinates to get how much the finger moved. – Xaver Kapeller Jun 05 '14 at 13:23

2 Answers2

2

You just have to calculate the difference between the x and y coordinates each time you get an ACTION_MOVE event. Try something like this:

public abstract class ScrollTouchListener implements View.OnTouchListener {

    private double x = 0;
    private double y = 0;

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

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // User started scrolling
                x = event.getX();
                y = event.getY();
                onScrollStarted(x, y);
                return true;

            case MotionEvent.ACTION_UP:
                // User stopped scrolling
                x = event.getX();
                y = event.getY();
                onScrollEnded(x, y);
                return true;

            case MotionEvent.ACTION_MOVE:
                // Finger was moved get new x and y coordinates 
                // and calculate the difference
                double newX = event.getX();
                double newY = event.getY();

                double difX =  x - newX;
                double difY =  y - newY;

                onScroll(difX, difY);

                x = newX;
                y = newY;
                return true;

            default:
                return false;
        }
    }

    protected abstract void onScrollStarted(double x, double y);
    protected abstract void onScroll(double deltaX, double deltaY);
    protected abstract void onScrollEnded(double x, double y);
}

You can use it like this:

scrollView.setOnTouchListener(new ScrollTouchListener() {
    @Override
    protected void onScrollStarted(double x, double y) {
        // Called when you start scrolling. 
        // x and y are the coordinates where the user started scrolling.     
    }

    @Override
    protected void onScroll(double deltaX, double deltaY) {
        // Called while scrolling. 
        // deltaX and deltaY tell you how much the finger was moved.
    }

    @Override
    protected void onScrollEnded(double x, double y) {
        // Called when you stop scrolling. 
        // x and y are the coordinates where the user stopped scrolling.  
    }
});
Xaver Kapeller
  • 49,491
  • 11
  • 98
  • 86
  • Probably this is a good solution, but in my case it doesn't work. It calcuates an offset from top, a delta, but it prevents scrolling. See http://stackoverflow.com/questions/3327087/how-to-get-the-current-y-offset-of-a-scrollview. – CoolMind Nov 02 '15 at 15:32
  • @CoolMind setting an on touch listener and consuming the touch events of course means that the `ScrollView` won't scroll. That's kinda the point. – Xaver Kapeller Nov 02 '15 at 15:36
1

There is my solution, works perfectly, try to read the code

public class CustomScrollView extends NestedScrollView
{

private boolean mIsScrolling;
private boolean mIsTouching;
private OnScrollListener mOnScrollListener;
private Runnable mScrollingRunnable;

public interface OnScrollListener
{
    void onScrollChanged(CustomScrollView scrollView, int x, int y, int oldX, int oldY);

    void onEndScroll(CustomScrollView scrollView);

    void onGoUp();

    void onGoDown();
}

public CustomScrollView(final Context context)
{
    super(context);
}

public CustomScrollView(final Context context, final AttributeSet attrs)
{
    super(context, attrs);
}

public CustomScrollView(final Context context, final AttributeSet attrs, final int defStyleAttr)
{
    super(context, attrs, defStyleAttr);
}

private int y = 0;

@Override
public boolean dispatchTouchEvent(MotionEvent iEv)
{
    if (isEnabled())
    {

        processEvent(iEv);

        super.dispatchTouchEvent(iEv);

        return true; //to keep receive event that follow down event
    }
    return super.dispatchTouchEvent(iEv);
}

private void processEvent(final MotionEvent iEv)
{
    switch (iEv.getAction())
    {
        case MotionEvent.ACTION_DOWN:
            y = (int) iEv.getY();
            break;

        case MotionEvent.ACTION_UP:
            y = (int) iEv.getY();

            if (mIsTouching && !mIsScrolling)
            {
                if (mOnScrollListener != null)
                {
                    //If you need to know when end of scrolling just uncomment
                    mOnScrollListener.onEndScroll(this);
                }
            }

            mIsTouching = false;
            break;
        case MotionEvent.ACTION_MOVE:
            mIsTouching = true;
            mIsScrolling = true;

            int newY = (int) iEv.getY();
            int difY = y - newY;

            int MAX_VALUE = 200;
            int MIN_VALUE = -200;
            if (difY > MAX_VALUE)
            {
                AppUtils.printLog(Log.ERROR, "TAG", "difY down : " + difY + " , y : " + y + ", newY : " + newY);
                if (mOnScrollListener != null)
                {
                    mOnScrollListener.onGoDown();
                }
                y = newY;
            }
            else if (difY < MIN_VALUE)
            {
                AppUtils.printLog(Log.ERROR, "TAG", "difY  up : " + difY + " , y : " + y + ", newY : " + newY);
                if (mOnScrollListener != null)
                {
                    mOnScrollListener.onGoUp();
                }
                y = newY;
            }

            break;
    }
}

@Override
protected void onScrollChanged(int iX, int iY, int iOldX, int iOldY)
{
    super.onScrollChanged(iX, iY, iOldX, iOldY);

    if (Math.abs(iOldX - iX) > 0)
    {
        if (mScrollingRunnable != null)
        {
            removeCallbacks(mScrollingRunnable);
        }

        mScrollingRunnable = new Runnable()
        {
            public void run()
            {
                if (mIsScrolling && !mIsTouching)
                {
                    if (mOnScrollListener != null)
                    {
                        mOnScrollListener.onEndScroll(CustomScrollView.this);
                    }
                }

                mIsScrolling = false;
                mScrollingRunnable = null;
            }
        };

        postDelayed(mScrollingRunnable, 200);
    }

    if (mOnScrollListener != null)
    {
        mOnScrollListener.onScrollChanged(this, iX, iY, iOldX, iOldY);
    }
}

public OnScrollListener getOnScrollListener()
{
    return mOnScrollListener;
}

public void setOnScrollListener(OnScrollListener mOnEndScrollListener)
{
    this.mOnScrollListener = mOnEndScrollListener;
}
}

Usage : Just add this custom view in XML

<ui.customWidgets.CustomScrollView
        android:id="@+id/scroll_frag_detail"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:scrollbars="none"
        app:behavior_overlapTop="192dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

           <!--Your code here-->

        </LinearLayout>

    </ui.customWidgets.CustomScrollView>

in code

mScrollView.setOnScrollListener(new CustomScrollView.OnScrollListener()
    {
        @Override
        public void onScrollChanged(final CustomScrollView scrollView, final int x, final int y, final int oldX, final int oldY)
        {

        }

        @Override
        public void onEndScroll(final CustomScrollView scrollView)
        {

        }

        @Override
        public void onGoUp()
        {

        }

        @Override
        public void onGoDown()
        {

        }
    });
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121