检测适配器中的滚动方向(向上/向下)

Waz*_*_Be 16 animation android listview scroll direction

我想在我的项目中模仿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);
Run Code Online (Sandbox Code Playgroud)

这似乎很糟糕,因为并非所有元素都是动画的:

所以我最后使用了适配器的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);
Run Code Online (Sandbox Code Playgroud)

结果太棒了,我真的很开心!

不幸的是,它只有在我从列表的顶部滚动到底部时才有效!

我想在另一边滚动时使它工作,我需要改变一点TranslateAnimation.

所以我的问题是,有没有办法检测我是否在我的适配器中向上或向下滚动?

Wro*_*lai 22

分配OnScrollListener给你的ListView.创建一个标志,指示用户是向上还是向下滚动.通过检查当前第一个可见项位置是否等于多于或小于前一个第一个可见项位置,为该标志设置适当的值.把那张支票放进去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;
    } 
}
Run Code Online (Sandbox Code Playgroud)

检查是否mIsScrollingUp为真或假getView(),并相应地分配动画.

  • 如果您向上或向下滚动,这并不能真正告诉您,因为第一个可见项目在不可见之后才会更改.在我的情况下,我实际上需要一个常量回调,因为列表是滚动的. (11认同)

Waz*_*_Be 19

我最后这样做了:

@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;

}
Run Code Online (Sandbox Code Playgroud)


Den*_*age 6

这是我遇到的最简单、最简单的方法。它就像一个魅力。

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
                    }
                }
            });
Run Code Online (Sandbox Code Playgroud)


小智 5

更复杂的解决方案(在listview中处理长项目高度)

  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();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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;
            }
        }
        });
    
    Run Code Online (Sandbox Code Playgroud)


mav*_*k97 5

接受的答案并没有真正"检测"向上或向下滚动.如果当前可见项目非常庞大,它将无法工作.使用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
    }
});
Run Code Online (Sandbox Code Playgroud)