2013-04-18 24 views
30

Khi tôi đặt onScrollListener cho số ListView, số này gọi là onScroll. Điều này gây ra sự cố do một số thứ chưa được khởi tạo.onScroll được gọi khi tôi đặt listView.onScrollListener (this), nhưng không có bất kỳ liên lạc nào

Điều này có bình thường không? Lưu ý: điều này đang xảy ra mà không cần tôi chạm vào điện thoại.

public class MainActivity1 extends Activity implements OnClickListener, OnScrollListener { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.layout1); 

    ListView lv = (ListView)findViewById(R.id.listview1); 
    lv.setOnScrollListener(this); 
    ... 
} 
... 
public void onScroll(AbsListView view, int firstVisibleItem, 
     int visibleItemCount, int totalItemCount){ 
    if(firstVisibleItem+visibleItemCount == totalItemCount){ 
     pullContactList(); 
    } 
} 
+0

có cái gì đó sai. oncreate là phương thức đầu tiên được gọi từ một hoạt động – stinepike

+0

xấu của tôi, nó thực sự được gọi khi onCreate gọi setOnScrollListner. điều này có bình thường không? – Siavash

+0

những gì chưa được khởi tạo? Các công cụ trong pullContactList()? – LuxuryMode

Trả lời

23

Đó là bình thường vì các mã nguồn cho setOnScrollListener trong AbsListView (lớp cha của ListView) thực hiện điều này:

public void setOnScrollListener(OnScrollListener l) { 
     mOnScrollListener = l; 
     invokeOnItemScrollListener(); 
    } 

invokeOnItemScrollListener thực hiện điều này:

/** 
    * Notify our scroll listener (if there is one) of a change in scroll state 
*/ 
    void invokeOnItemScrollListener() { 
     if (mFastScroller != null) { 
      mFastScroller.onScroll(this, mFirstPosition, getChildCount(), mItemCount); 
     } 
     if (mOnScrollListener != null) { 
      mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount); 
     } 
     onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these. 
    } 

tùy thuộc vào những gì nó là bạn đang cố gắng làm, có một số cách để tránh vấn đề này.

EDIT:

Vì bạn chỉ muốn làm điều này nếu người dùng thực sự cuộn, tôi giả sử bạn có thể làm một cái gì đó như:

lv.setOnTouchListener(new OnTouchListener() { 
       @Override 
       public boolean onTouch(View view, MotionEvent motionEvent) { 
        if(view == lv && motionEvent.getAction() == MotionEvent.ACTION_SCROLL) { 
         userScrolled = true; 
    } 
return false; 
       } 
      }); 

Sau đó ..

lv.setOnScrollListener(new AbsListView.OnScrollListener() { 
    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, 
      int visibleItemCount, int totalItemCount){ 
     if(userScrolled && firstVisibleItem+visibleItemCount == totalItemCount){ 
      pullContactList(); 
     } 
    } 

}); 
+0

Tôi chỉ muốn onScroll không được gọi là lần đầu tiên, tôi muốn nó được gọi chỉ khi người dùng cuộn. Cảm ơn. (Tôi nhận ra rằng tôi có thể di chuyển setonscrolllistner về sau trong mã, nhưng tôi muốn tìm hiểu cách làm thế nào để thực hiện theo cách khác) – Siavash

+2

cho đầy đủ: bạn quên một câu lệnh trả về trong trình nghe onTouch của bạn –

+2

Tôi không thể tin rằng hành vi đó không được đề cập trong tài liệu. – blahdiblah

56

Chỉ cần một nhắc nhở, theo javadoc của

MotionEvent.ACTION_SCROLL :

Hành động này luôn được gửi đến cửa sổ hoặc xem dưới con trỏ, có thể không phải là cửa sổ hoặc chế độ xem hiện đang được chạm.

Hành động này không phải là sự kiện chạm để nó được gửi đến onGenericMotionEvent (MotionEvent) thay vì onTouchEvent (MotionEvent).

Do đó, motionEvent.getAction() sẽ không bao giờ nhận được sự kiện SCROLL. Check for MOVE sẽ làm công việc

Bạn cũng có thể làm điều tương tự như trong phương pháp onScrollStateChanged của OnScrollListener

@Override 
public void onScrollStateChanged(AbsListView view, int scrollState) { 
     if(scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){ 
      userScrolled = true; 
     } 
} 
+7

Đây là câu trả lời đúng. –

+0

hi đôi khi phương thức 'onScrollStateChanged()' không được gọi, ví dụ khi gọi phương thức 'adapter.notificationDataSetChange()', nó sẽ bỏ qua phương thức này và vào phương thức 'onScrollStateChanged()' .so phương thức này không phù hợp – Carl

+0

Tôi biết đây là câu trả lời cũ, nhưng tôi chỉ tình cờ gặp vấn đề này. Tôi hiểu tại sao nó xảy ra khi tôi đọc mã nguồn cho 'AbsListView', nhưng tôi không hiểu tại sao nó lại xảy ra. Có ai có thể khai sáng cho tôi không? – Darwind

0

Bạn có thể làm nhiệm vụ cần thiết chỉ khi visibleItemCount> 0;

public void onScroll(AbsListView view, int firstVisibleItem, 
     int visibleItemCount, int totalItemCount){ 
    if (visibleItemCount > 0){ 
     //perform the task to be done 
    } 
} 
3

tôi sử dụng giải pháp này và nó hoạt động tốt đối với tôi:

public void onScrollStateChanged(AbsListView view, int scrollState) { 
      if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { 
       canScroll = false; 
      } else if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING || 
        scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 
       canScroll = true; 

      } 
     } 
0

giải pháp Làm việc đối với tôi !!! kết hợp của câu trả lời ở trên tôi đã thực hiện các giải pháp !! nhờ @LuxuryMode và @CrazyGreenHand

TouchListener của tôi: từ MotionEvent.ACTION_SCROLL không trigged i dùng MOVE hành động

expandableListView.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 
      if(view == expandableListView && motionEvent.getAction() == MotionEvent.ACTION_MOVE) { 
       userScrolled = true; 
      } 
      return false; 
     } 
    }); 

My Scroll Thính giả:

expandableListView.setOnScrollListener(new AbsListView.OnScrollListener() { 
     @Override 
     public void onScrollStateChanged(AbsListView absListView, int i) { 

     } 

     @Override 
     public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
      if (firstVisibleItem == 0){ 
       swipeRefreshLayout.setEnabled(true); 
      }else { 
       swipeRefreshLayout.setEnabled(false); 
      } 
      int lastVisibleItem = absListView.getLastVisiblePosition(); 
      if (userScrolled&&!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { 
       onLoadMore(); 
       isLoading = true; 
      } 
      Log.d(TAG, "onScroll: firstVisibleItem=>"+firstVisibleItem+"==>visibleItemCount=>"+visibleItemCount+"==>totalItemCount==>"+totalItemCount+"==>lastVisibleItem==>"+lastVisibleItem); 
     } 
    }); 
Các vấn đề liên quan