2010-11-24 41 views
22

Tôi có nội dung cố định trong chế độ xem văn bản bên trong chế độ xem cuộn. Khi người dùng cuộn đến một vị trí nhất định, tôi muốn bắt đầu một hoạt động hoặc kích hoạt một Toast.Android scrollview onScrollChanged

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" android:layout_height="fill_parent" 
android:id="@+id/scroller"> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView android:layout_width="fill_parent" android:id="@+id/story" 
    android:layout_height="wrap_content" android:text="@string/lorem" 
    android:gravity="fill" /> 
</LinearLayout> 
</ScrollView> 

Vấn đề của tôi là trong việc thực hiện các phương pháp bảo vệ onScrollChanged để tìm ra vị trí của các điểm di chuyển.

Tôi đã tìm thấy câu trả lời là this, có một giải pháp dễ dàng hơn cho việc này thay vì khai báo một giao diện hay không, qua đi xe scrollview vv như đã thấy trên liên kết tôi đã đăng?

+1

bạn có thể sử dụng http: // stackoverflow.com/questions/10316743/detect-end-of-scrollview –

Trả lời

11

số

scrollview không cung cấp một người biết lắng nghe cho các sự kiện cuộn hoặc thậm chí là một cách để kiểm tra xuống người dùng đã cuộn bao xa, vì vậy bạn phải làm những gì được đề xuất bởi các liên kết.

+13

Có một phương thức onScrollChanged có thể bị ghi đè. Likelwise getScrollX, getScrollY có thể được sử dụng. –

+0

Dường như câu trả lời này không hợp lệ ngay bây giờ. Bắt đầu từ API 23 (M) có một người nghe được gọi là "OnScrollChangeListener" scrollView.setOnScrollChangeListener (mới View.OnScrollChangeListener() { @Override public void onScrollChange (Xem v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { // làm việc với các thông số } }); –

8

Thực ra có cách để biết người dùng đã cuộn bao xa. Phương thức getScrollY() từ ScrollView cho bạn biết.

+0

Không, theo điều này: http://stackoverflow.com/questions/2132370/android-listview-getscrolly-does-it-work – Timmmm

+3

Tôi đã sử dụng giải pháp này trong một dự án trong công ty của mình. Tôi kiểm tra tất cả mọi thứ trước khi tôi đăng một cái gì đó ở đây. Có lẽ bạn nên làm như vậy? – tulio84z

+0

Xin lỗi, đã đọc sai câu hỏi. Nó hoạt động cho một 'ScrollView' nhưng không phải là' ListView' hoặc 'GridView'. – Timmmm

47

Có một cách dễ dàng hơn nhiều so với phân lớp ScrollView. Các đối tượng ViewTreeObserver của ScrollView có thể được sử dụng để nghe cuộn.

Kể từ khi đối tượng ViewTreeObserver có thể thay đổi trong suốt cuộc đời của ScrollView, chúng tôi cần phải đăng ký một OnTouchListener trên ScrollView để có được nó ViewTreeObserver tại thời điểm di chuyển.

final ViewTreeObserver.OnScrollChangedListener onScrollChangedListener = new 
          ViewTreeObserver.OnScrollChangedListener() { 

    @Override 
    public void onScrollChanged() { 
     //do stuff here 
    } 
}; 

final ScrollView scrollView = (ScrollView) findViewById(R.id.scroller); 
scrollView.setOnTouchListener(new View.OnTouchListener() { 
    private ViewTreeObserver observer; 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if (observer == null) { 
      observer = scrollView.getViewTreeObserver(); 
      observer.addOnScrollChangedListener(onScrollChangedListener); 
     } 
     else if (!observer.isAlive()) { 
      observer.removeOnScrollChangedListener(onScrollChangedListener); 
      observer = scrollView.getViewTreeObserver(); 
      observer.addOnScrollChangedListener(onScrollChangedListener); 
     } 

     return false; 
    } 
}); 
+1

Điều đó không nhất thiết phải dễ dàng hơn việc phân lớp 'ScrollView'. Nó thực sự là mã hơn. Nếu bạn phân lớp, bạn chỉ có thể ghi đè lên phương thức 'onScrollChanged'. –

+1

Tôi đã thử điều này và dường như kích hoạt sự kiện 20 lần hoặc nhiều hơn cho cùng một giá trị Y cuộn. Nó không có vẻ lý tưởng. – RandomEngy

+0

Vâng ... có một vấn đề lớn với mã này! Và vấn đề này là kết quả trong các lỗi như một từ bình luận @RandomEngy. Vì vậy, tôi không biết tại sao nó lại được bình chọn rất cao. Nó cho biết thêm người nghe này ON EVERY TOUCH EVENT ON SCROLL. Vì vậy, về cơ bản nếu bạn nhấp vào cuộn của bạn 20 lần nó sẽ dẫn đến 20 cuộc gọi đến người nghe. Trình nghe chỉ nên được thêm một lần. Ví dụ như thế này: 'scrollView.getViewTreeObserver(). AddOnScrollChangedListener (mới ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() {// do stuff}});'. KHÔNG PHẢI TRÊN PHƯƠNG PHÁP TOUCH –

9

Câu hỏi này là khá cũ, nhưng trong trường hợp ai đó nó giảm đi (như tôi):

Bắt đầu với API 23, Android của ViewOnScrollChangeListenermatching setter.

NestedScrollView từ thư viện Hỗ trợ cũng hỗ trợ cài đặt trình xử lý cuộn ngay cả trước cấp API đó. Theo như tôi biết, NestedScrollView có thể được sử dụng để thay thế cho bình thường ScrollView mà không có bất kỳ vấn đề gì.

+0

không có khả năng tương thích ngược tho – definera

+0

@ xác định tốt, có 'NestedScrollView' trong lib Hỗ trợ, bạn csn sử dụng insead của' Scrollview' thông thường mà không có vấn đề – Lovis

+0

Xin lỗi, vì một số lý do tôi đã bỏ lỡ phần mà bạn đề cập đến nó .. Cảm ơn anyway – definera

2

Tôi đã mở rộng scrollView của mình. This link có thể hữu ích.

class MyScroll extends ScrollView { 
    boolean onTop=true; 
    @Override 
    protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
     //Log.d(TAG, "scroll changed: " + this.getTop() + " "+t); 
     if(t <= 0){ 
      onTop = true; 
      //Log.d(TAG, "scroll top: " + t); 
      super.onScrollChanged(l, t, oldl, oldt); 
      return; 
      // reaches the top end 
     } 
     onTop = false; 

     View view = (View) getChildAt(getChildCount()-1); 
     int diff = (view.getBottom()-(getHeight()+getScrollY()+view.getTop()));// Calculate the scrolldiff 
     if(diff <= 0){ 
      // if diff is zero, then the bottom has been reached 
     } 
     super.onScrollChanged(l, t, oldl, oldt); 
    } 
} 
0

Chỉ cần sử dụng NestedScrollNestedScroll.setOnScrollChangeListener().

0

ready for use component, giúp nghe các sự kiện cuộn của các chế độ xem tùy ý trong Android. Bên trong thành phần này thêm trình xử lý sự kiện cuộn ViewTreeObserver trên thiết bị có API Android cũ (tương tự như được đề xuất trong câu trả lời của Shubhadeep Chaudhuri) và Xem trình xử lý sự kiện cuộn trên thiết bị có API Android mới (API cấp 23+).

0

Bắt đầu từ API 23 Android M, bạn có thể sử dụng OnScrollChangeListener.

scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { 
     @Override 
     public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { 
      //work with parameters 
     } 
    }); 
1

NestedScrollView giống như android.widget.ScrollView, nhưng nó hỗ trợ hoạt động như cả cha và mẹ cuộn lồng nhau trên cả phiên bản Android mới và cũ.

1 - Sử dụng NestedScrollView ràng buộc thay vì scrollview

2 - Set Scroll người nghe, như thế này, để phát hiện trục Y di chuyển cho một headerView bằng ví dụ

nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { 

     @Override 
     public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { 
      Log.d(TAG, "onScrollChangeForY - scrollY: " + scrollY + " oldScrollY: " + oldScrollY); 

      int MOVE = -1, SCROLL_UP = 0, SCROLL_DOWN = 1; 
      float initialPositionY = headerView.getY(); 

      MOVE = scrollY > oldScrollY ? SCROLL_UP : SCROLL_DOWN; 

      if (MOVE == SCROLL_UP) { 

       int incrementY = scrollY - oldScrollY; 

       headerView.setY(initialPositionY - incrementY); 

      } else { 

       int incrementY = oldScrollY - scrollY; 

       headerView.setY(initialPositionY + incrementY); 
      } 
     } 
    }); 
Các vấn đề liên quan