onScrollListener
にListView
を設定すると、onScroll
が呼び出されます。特定のものが初期化されていないため、これによりクラッシュが発生します。
これは正常ですか?注:これは私が電話に触れなくても起きています。
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();
}
}
setOnScrollListener
のAbsListView
のソースコード(ListView
のスーパークラス)がこれを行うので、これは正常です。
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener = l;
invokeOnItemScrollListener();
}
invokeOnItemScrollListener
はこれを行います:
/**
* 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.
}
何をしようとしているかに応じて、この問題を回避する方法はいくつかあります。
編集:
ユーザーが実際にスクロールした場合にのみこれを実行したいので、次のようなことができると思います。
lv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(view == lv && motionEvent.getAction() == MotionEvent.ACTION_SCROLL) {
userScrolled = true;
}
return false;
}
});
それから.
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount){
if(userScrolled && firstVisibleItem+visibleItemCount == totalItemCount ){
pullContactList();
}
}
});
のjavadocによると、単なるリマインダー
MotionEvent.ACTION_SCROLL :
このアクションは常にポインターの下のウィンドウまたはビューに配信されますが、現在タッチされているウィンドウまたはビューとは異なる場合があります。
このアクションはタッチイベントではないため、onTouchEvent(MotionEvent)ではなくonGenericMotionEvent(MotionEvent)に配信されます。
したがって、motionEvent.getAction()
はSCROLLイベントを取得しません。 MOVEを確認してください
onScrollStateChanged
のOnScrollListener
メソッドでも同様のことができます
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
userScrolled = true;
}
}
私はこのソリューションを使用し、それは私にとってはうまくいきます:
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;
}
}
私のために働いたソリューション!!!上記の答えの組み合わせで解決策を作りました!! @LuxuryModeと@CrazyGreenHandに感謝
My TouchListener: MotionEvent.ACTION_SCROLLがトリガーされなかったため、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;
}
});
My Scroll Listener:
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);
}
});
VisibleItemCount> 0の場合にのみ、必要なタスクを実行できます。
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount){
if (visibleItemCount > 0 ){
//perform the task to be done
}
}