Make scrollView autoscroll with drag and drop on Android

I searched everything but could not find a solution.

I have a view (lets call it myView) inside scrollview. myView is larger than the screen. Since I can get the relative x, y position of my finger inside myView, I would like to make scrollView autoscroll to the upper / lower side when my finger enters a certain upper / lower threshold. I have some ideas, namely moving the drag and drop location to the screen position, but this did not solve this problem.

early

amuses

+4
source share
3 answers

Ok, I figured it out myself.

First I had to extend the ScrollView class and add the OnScrollViewListener interface.

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

Later in my work, I inserted the mScrollDistance member, which indicates the number of pixels that 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 always gets a new value, and the drag location will be moved to the view location. I tested this and it works with layouts / views that are larger than the screen size.

Hope this helps.

+9
source

I came up with a different solution, and I am pleased with that.

I want to be able to drag and drop views inside a ScrollView. ScrollView then needs to scroll up and down automatically when the shadow reaches the edges of the scroll.

As a result, I got a solution that detects that the dropout area is completely visible inside the scrollview (with a margin of 100 pixels) and otherwise adjust the scroll view.

 @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!

+4
source

I used a timer in In C #

 ScrollCalendar ScrollCalendar = new ScrollCalendar (yourScrollView); 

Inside a drag event

  public bool OnDrag (View v, DragEvent e) { var dragshadow = new EventDateDragShadow (v); switch (e.Action) { case DragAction.Started: return true; case DragAction.Entered: break; case Android.Views.DragAction.Location: if (e.GetY () < 90) { ScrollCalendar.StartScroll (-15); } else if (e.GetY () > yourScrollView.Height - 90) { ScrollCalendar.StartScroll (15); } else ScrollCalendar.StopScroll (); return (true); case DragAction.Exited: return true; case DragAction.Drop: return true; case DragAction.Ended: ScrollCalendar.StopScroll (); v.SetOnDragListener (null); return true; } return true; } 

Class ScrollCalendar

 public class ScrollCalendar { private ScrollView Calendar; private System.Timers.Timer Timer; private int ScrollDistance; public ScrollCalendar(ScrollView calendar) { Calendar = calendar; Timer = new System.Timers.Timer(); Timer.Elapsed+=new ElapsedEventHandler(Scroll); Timer.Interval = 50; } public void StartScroll(int scrollDistance) { if (Timer.Enabled) { return; } ScrollDistance = scrollDistance; Timer.Enabled = true; } public void StopScroll() { Timer.Enabled = false; } private void Scroll(object source, ElapsedEventArgs e) { Calendar.SmoothScrollBy (0, ScrollDistance); } } 

Change the StartScroll and Timer.Interval values ​​to adjust the scroll speed.

+1
source

All Articles