web-dev-qa-db-ja.com

アダプターのスクロール方向の検出(上/下)

私のプロジェクトでGoogle Plusアプリケーションを模倣しようとしています。これは現在リファレンスのようです。

スクロール時のリストビュー効果は本当にいいですし、同様のことをしたいと思います。

私はLayoutAnimationControllerから始めました http://Android-er.blogspot.be/2009/10/listview-and-listactivity-layout.html

LayoutAnimationController controller 
   = AnimationUtils.loadLayoutAnimation(
     this, R.anim.list_layout_controller);
  getListView().setLayoutAnimation(controller);

すべての要素がアニメーション化されているわけではないので、それは悪いようです:

だから私はアダプターのgetViewを使用してこれを使用することで終わりました:

        AnimationSet set = new AnimationSet(true);

        Animation animation = new AlphaAnimation(0.0f, 1.0f);
        animation.setDuration(800);
        set.addAnimation(animation);

        animation = new TranslateAnimation(
            Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 1.0f,Animation.RELATIVE_TO_SELF, 0.0f
        );
        animation.setDuration(600);
        set.addAnimation(animation);

        row.startAnimation(set);

結果は素晴らしいです、そして私はそれで本当に満足しています!

残念ながら、それは私がリストの上から下にスクロールしたときにのみ機能します!

反対側にスクロールするときにそれを動作させたいので、TranslateAnimationを少し変更する必要があります。

だから私の質問、私のアダプターを上または下にスクロールしたかどうかを検出する方法はありますか?

16
Waza_Be

これは私が出会った最も簡単でシンプルな方法です。そしてそれは魅力のように働きます。

view.addOnScrollListener(new View.OnScrollListener() {
                @Override
                public void onScrolled(@NonNull View view, int dx, int dy) {
                    if (dy > 0) {
                        //Scrolling down
                    } else if (dy < 0) {
                        //Scrolling up
                    }
                }
            });
0
Dennis Murage

OnScrollListenerListViewに割り当てます。ユーザーが上または下にスクロールしているかどうかを示すフラグを作成します。現在のfirst表示アイテムの位置が以前のfirst表示アイテムの位置。そのチェックをonScrollStateChanged()の中に入れます。

サンプルコード:

_private int mLastFirstVisibleItem;
private boolean mIsScrollingUp;

public void onScrollStateChanged(AbsListView view, int scrollState) {
    final ListView lw = getListView();

    if (view.getId() == lw.getId()) {
        final int currentFirstVisibleItem = lw.getFirstVisiblePosition();

        if (currentFirstVisibleItem > mLastFirstVisibleItem) {
            mIsScrollingUp = false;
        } else if (currentFirstVisibleItem < mLastFirstVisibleItem) {
            mIsScrollingUp = true;
        }

        mLastFirstVisibleItem = currentFirstVisibleItem;
    } 
}
_

getView()mIsScrollingUpがtrueまたはfalseかどうかを確認し、それに応じてアニメーションを割り当てます。

22
Wroclai

私はこれを行うことで終わりました:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Log.i("",position+" - "+lastposition);

    if (position >= lastposition)
        animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
                Animation.RELATIVE_TO_SELF, 1.0f,
                Animation.RELATIVE_TO_SELF, 0.0f);
    else
        animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
                Animation.RELATIVE_TO_SELF, -1.0f,
                Animation.RELATIVE_TO_SELF, 0.0f);

    animation.setDuration(600);
    set.addAnimation(animation);

    row.startAnimation(set);

    lastposition = position;

}
19
Waza_Be

より複雑なソリューション(リストビューで長いアイテムの高さで作業)

  1. カスタムリストビューを作成する

    public class ScrollDetectingListView extends ListView {
        public ScrollDetectingListView(Context context) {
            super(context);
        }
    
        public ScrollDetectingListView(Context context, AttributeSet attrs) {
            super(context,attrs);
        } 
    
        public ScrollDetectingListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        //we need this protected method for scroll detection
        public int getVerticalScrollOffset() {
            return computeVerticalScrollOffset();
        }
    }
    
  2. OnScrollをオーバーライド

        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
    
        private int mInitialScroll = 0;
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
    
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            int scrolledOffset = listView.getVerticalScrollOffset();
            if (scrolledOffset!=mInitialScroll) {
                //if scroll position changed
                boolean scrollUp = (scrolledOffset - mInitialScroll) < 0;
                mInitialScroll = scrolledOffset;
            }
        }
        });
    
5
recoilme

受け入れられた回答は、実際に上下にスクロールすることを「検出」するものではありません。現在表示されているアイテムが非常に大きい場合は機能しません。 onTouchListenerを使用する方法です。

これは私が使用したコードスニペットです:

listView.setOnTouchListener(new View.OnTouchListener() {
    float initialY, finalY;
    boolean isScrollingUp;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = MotionEventCompat.getActionMasked(event);

        switch(action) {
            case (MotionEvent.ACTION_DOWN):
                initialY = event.getY();
            case (MotionEvent.ACTION_UP):
                finalY = event.getY();

                if (initialY < finalY) {
                    Log.d(TAG, "Scrolling up");
                    isScrollingUp = true;
                } else if (initialY > finalY) {
                    Log.d(TAG, "Scrolling down");
                    isScrollingUp = false;
                }
            default:
        }

        if (isScrollingUp) {
            // do animation for scrolling up
        } else {
            // do animation for scrolling down
        }

        return false; // has to be false, or it will freeze the listView
    }
});
5
maverick97

これを試して 。お役に立てば幸いです。 @Gal Rom Answerからのロジック。

lv.setOnScrollListener(new OnScrollListener() {
        private int mLastFirstVisibleItem;

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {

            if(mLastFirstVisibleItem<firstVisibleItem)
            {
                Log.i("SCROLLING DOWN","TRUE");
            }
            if(mLastFirstVisibleItem>firstVisibleItem)
            {
                Log.i("SCROLLING UP","TRUE");
            }
            mLastFirstVisibleItem=firstVisibleItem;

        }
    });
4
IntelliJ Amiya

これが私のアプローチです:スクロールした量に関するフィードバックがすぐに得られます:OnScroll、リストの最初の項目のトップポジションを取得できます。実際のスクロール位置情報をすぐに取得するのはかなり信頼できます。

listView.getChildAt(0).getTop()
2
Nelson Ramirez
list.setOnScrollListener(new OnScrollListener() {
        int last_item;
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if(last_item<firstVisibleItem+visibleItemCount-1){
                System.out.println("List is scrolling upwards");
            }
            else if(last_item>firstVisibleItem+visibleItemCount-1){
                System.out.println("List is scrolling downwards");
            }
             last_item = firstVisibleItem+visibleItemCount-1;
        }
    });

最後に表示されたアイテムの位置に基づいて、リストビューが上向きか下向きかを決定します。

0
Karthik Rk

ビューなどの位置に依存しない一般的なソリューション。垂直スクロールオフセットを確認して、前のスクロールオフセットと比較してください。新しい値が古い値より大きい場合、ユーザーは下にスクロールしており、その逆も同様です。

// [START check vertical scroll direction]
int oldScrollOffset = 0;

listView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
        @Override
        public void onScrollChange(View view, int i, int i1, int i2, int i3) {

            Boolean scrollDirectionDown;

            int newScrollOffset = listView.computeVerticalScrollOffset();

            if (newScrollOffset > oldScrollOffset) {
                scrollDirectionDown = true;
            } else {
                scrollDirectionDown = false;
            }

            oldScrollOffset = newScrollOffset;

            if (scrollDirectionDown) {
                // Update accordingly for scrolling down
                Log.d(TAG, "scrolling down");
            } else {
                // Update accordingly for scrolling up
                Log.d(TAG, "scrolling up");
            }

    });
// [END check vertical scroll direction]
0
Damon

私はこれよりはるかに簡単なソリューションを使用しました:

public class ScrollDetectingListView extends ListView

...

setOnScrollListener( new OnScrollListener() 
{

    private int mInitialScroll = 0;

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) 
    {
        int scrolledOffset = computeVerticalScrollOffset();

        boolean scrollUp = scrolledOffset > mInitialScroll;
        mInitialScroll = scrolledOffset;
    }


    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {


    }

}
0
Vaiden