I searched all over, but could not find a solution.
I have a view (lets call it myView) inside a scrollview. myView is bigger than the screen. Since I'm able to get the relative x,y position of my finger inside myView, I would like to make the scrollView autoscroll to the top/bottom when my finger enters a certain top/bottom threshold. I have some ideas, namely translating the drag location to the screen position but this did not solve this problem.
thanks in advance
cheers
NestedScrollView is just like ScrollView , but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.
android:fillViewport. Defines whether the scrollview should stretch its content to fill the viewport.
All right I figured it out by myself.
First I had to extend the ScrollView class and added an interface OnScrollViewListener.
public class MyScrollView extends ScrollView {
    private OnScrollViewListener mListener;
    public MyScrollView(Context c, AttributeSet attrs) {
       super(c, attrs);
    }
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
       super.onScrollChanged(l, t, oldl, oldt);
       if (mListener != null) {
           mListener.onScrollChanged((OnScrollViewListener) this);
       }
    }
    public void setOnScrollViewListener(OnScrollViewListener listener) {
       mListener = listener;
    }
    public static interface OnScrollViewListener {
       public void onScrollChanged(OnScrollViewListener listener);
    }
}
Next in my Activity I inserted a member mScrollDistance that indicates the amount of pixels the user scrolls.
public class ScrollActivity extends Activity {
   private int mScrollDistance;
   @Override
   protected void OnCreate(...) {
     ...
     final MyScrollView myScrollView = (MyScrollView) findViewById(R.id.scroll_view);
     myScrollView.setOnScrollViewListener(new MyScrollView.OnScrollViewListener() {
          public void onScrollChanged(OnScrollViewListener listener) {
             mScrollDistance = listener.getScrollY();
          }
     }
     // making an drag and drop in an view that is inside the MyScrollView
     final LinearLayout myLayout = (LinearLayout)findViewById(R.id.linear_layout);
     myLayout.setOnDragListener(new View.OnDragListener() {
       public boolean onDrag (View v, DragEvent event) {
         int action = event.getAction();
         switch(action) {
            case DragEvent.ACTION_DRAG_STARTED: {
            }
            case DragEvent.ACTION_DRAG_LOCATION: {
              int y = Math.round(event.getY());
              int translatedY = y - mScrollDistance;
              int threshold = 50;
              // make a scrolling up due the y has passed the threshold
              if (translatedY < threshold) {
                 // make a scroll up by 30 px
                 myScrollView.scrollBy(0, -30);
              }
              // make a autoscrolling down due y has passed the 500 px border
              if (translatedY + threshold > 500) {
                 // make a scroll down by 30 px
                 myScrollView.scrollBy(0, 30);
              }
              // listen for more actions here
              // ...
            }
         }
       }
     }
Now, mScrollDistance gets always a new value and the drag location will be translated to the view location. I tested this and it works on layouts/views that are bigger than the screen size.
Hope that helps.
I came up with a different solution and I am happy with it.
I want to be able to drag and drop views inside a ScrollView. The ScrollView then needs to scroll up and down automatically when the shadow reaches the edges of the scroll view.
I ended up with a solution that detects wether the drop zone is completely visible inside the scrollview (with a 100px margin) and adjust the scroll view otherwise.
@Override
public boolean onDrag(View view, DragEvent event) {
    MainWidget dropZoneView = (MainWidget) view;
    int action = event.getAction();
    switch (action) {
        case DragEvent.ACTION_DRAG_STARTED:
        //(... other stuff happens here)
        case DragEvent.ACTION_DRAG_LOCATION:
            ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scroll);
            int topOfDropZone = dropZoneView.getTop();
            int bottomOfDropZone = dropZoneView.getBottom();
            int scrollY = mainScrollView.getScrollY();
            int scrollViewHeight = mainScrollView.getMeasuredHeight();
            Log.d(LOG_TAG,"location: Scroll Y: "+ scrollY + " Scroll Y+Height: "+(scrollY + scrollViewHeight));
            Log.d(LOG_TAG," top: "+ topOfDropZone +" bottom: "+bottomOfDropZone);
            if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
                mainScrollView.smoothScrollBy(0, 30);
            if (topOfDropZone < (scrollY + 100))
                mainScrollView.smoothScrollBy(0, -30);
            break;
        default:
            break;
    }
    return true;
}
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With