web-dev-qa-db-fra.com

onScroll est appelé quand je définis listView.onScrollListener (this), mais sans toucher

Lorsque je règle onScrollListener pour ma ListView, il appelle onScroll. Cela provoque un crash car certaines choses n’ont pas été initialisées.

Est-ce normal? Remarque: cela se produit sans même que je touche le téléphone.

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();
    }
}
30
Siavash

C'est normal car le code source de setOnScrollListener dans AbsListView (la superclasse de ListView) fait ceci:

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

et invokeOnItemScrollListener fait ceci:

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

en fonction de ce que vous essayez de faire, il existe plusieurs façons d'éviter ce problème.

MODIFIER: 

Puisque vous ne voulez faire cela que si l'utilisateur a réellement fait défiler, je suppose que vous pourriez faire quelque chose comme:

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

Ensuite..

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

});
23
LuxuryMode

Juste un rappel, selon le javadoc de 

MotionEvent.ACTION_SCROLL:

Cette action est toujours transmise à la fenêtre ou à la vue sous le pointeur, qui peut ne pas être la fenêtre ou la vue actuellement touchée. 

Cette action n'étant pas un événement tactile, elle est transmise à onGenericMotionEvent (MotionEvent) plutôt qu'à onTouchEvent (MotionEvent).

Par conséquent, motionEvent.getAction() n'obtiendra jamais l'événement SCROLL. Check for MOVE fera le travail

Vous pouvez également faire la même chose dans la méthode onScrollStateChanged de la méthode OnScrollListener

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

J'utilise cette solution et cela fonctionne bien pour moi:

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;

            }
        }
3
Farzad Farazmand

Solution travaillée pour moi !!! combinaison de réponse ci-dessus j'ai fait la solution !! grâce à @LuxuryMode et @CrazyGreenHand

Mon TouchListener: Depuis MotionEvent.ACTION_SCROLL non déclenché, j'ai utilisé l'action MOVE

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

Mon écouteur de défilement:

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

Vous pouvez effectuer la tâche nécessaire uniquement lorsque visibleItemCount> 0;

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