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