2011-09-08 50 views
3

我搜遍了所有內容,但找不到解決方案。使用拖放功能製作scrollView自動滾屏Android

我有一個視圖(讓我們稱之爲myView)內滾動視圖。 myView比屏幕大。由於我能夠獲得相對 x,y在myView中的手指位置,我希望當我的手指進入某個頂部/底部閾值時,使scrollView自動滾動到頂部/底部。 我有一些想法,即將拖動位置翻譯到屏幕位置,但這並沒有解決這個問題。

在此先感謝

歡呼

回答

9

好吧,我想通了我自己。

首先,我不得不擴展ScrollView類並添加了一個接口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); 
    } 
} 

接着在我的活動餘插入的構件mScrollDistance指示的 像素用戶滾動量。

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 
       // ... 
      } 
     } 
     } 
    } 

現在,mScrollDistance總是獲得一個新值,拖動位置將被轉換爲視圖位置。 我測試過它,它可以在比屏幕尺寸更大的佈局/視圖上工作。

希望有所幫助。

+1

感謝您的想法,儘管您不需要使用自定義ScrollView的全部工作。如果不使用自定義ScrollView和監聽器等來獲取mScrollDistance,則可以在計算translatedY變量時簡單地使用普通的ScrollView的getScrollY()方法。 – Ridcully

+1

我意識到你的解決方案只適用於只有一個元素被拖拽,並最終以完全不同的解決方案爲基礎重寫'dispatchDragEvent()'方法。如果有人對細節感興趣,請在這裏留言。 – Ridcully

+1

好吧,讓我們聽到它。 – Vivekanand

5

我想出了一個不同的解決方案,我很滿意。

我希望能夠在ScrollView中拖放視圖。當陰影到達滾動視圖的邊緣時,ScrollView需要自動上下滾動。

我最終得到了一個解決方案,它可以檢測滾動視圖內的拖放區域是否完全可見(100px的邊距),否則調整滾動視圖。

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

希望這有助於!

1

我使用的計時器中在C#

ScrollCalendar ScrollCalendar = new ScrollCalendar (yourScrollView); 

裏面的拖拽事件

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

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

} 

更改StartScroll值和Timer.Interval調整滾動的速度。