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

时间:2012-08-24 18:41:52

标签: android listview animation 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);

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

所以我最后使用了适配器的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。

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

11 个答案:

答案 0 :(得分:22)

ListView分配OnScrollListener。创建一个标志,指示用户是向上还是向下滚动。通过检查当前第一个可见项目位置是否等于多于或少于前一个第一个可见项目位置,为该标志设置适当的值。将该检查放在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;
    } 
}

mIsScrollingUp中检查getView()是真还是假,并相应地指定动画。

答案 1 :(得分:18)

我最终这样做了:

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

}

答案 2 :(得分: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();
        }
    }
    
  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;
            }
        }
        });
    

答案 3 :(得分:5)

接受的答案并没有真正“检测”向上或向下滚动。如果当前可见项目非常庞大,它将无法工作。使用SELECT p.id, p.person_name, d.department_name, c.phone_number FROM person p LEFT JOIN (SELECT *, ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY id) AS seq FROM department) d ON d.person_id = p.id And d.seq = 1 LEFT JOIN ( SELECT *, ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY id) AS seq FROM contact) c ON c.person_id = p.id And c.seq = 1; 是可行的方法。

这是我使用的代码段:

onTouchListener

答案 4 :(得分:3)

试试这个。我希望它对你有所帮助。来自@Gal Rom的逻辑答案。

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;

        }
    });

答案 5 :(得分:3)

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

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

答案 6 :(得分:2)

这是我的方法:它可以让您更直接地反馈您滚动的数量: OnScroll,您只需获取列表中第一项的最高排名即可。立即获取实际滚动位置信息非常可靠。

listView.getChildAt(0).getTop()

答案 7 :(得分:0)

我使用了这个更简单的解决方案:

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) {


    }

}

答案 8 :(得分:0)

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

根据最后一个可见项目的位置,我决定Listview是上升还是下降。

答案 9 :(得分:0)

不依赖于视图/等位置的一般解决方案。只需检查垂直滚动偏移并将其与上一个滚动偏移进行比较即可。如果新值大于旧值,则用户正在向下滚动,反之亦然。

// [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]

答案 10 :(得分:0)

view.setOnTouchListener(new View.OnTouchListener() {

        private long startClickTime;
        float y0 = 0;
        float y1 = 0;
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                y0 = motionEvent.getY();
                startClickTime = System.currentTimeMillis();

            } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                if (System.currentTimeMillis() - startClickTime < ViewConfiguration.getTapTimeout()) {

                    // Touch was a simple tap. Do whatever.

                } else {
                    y1 = motionEvent.getY();
                    // Touch was a not a simple tap.
                    if (y1 - y0 > 50) {
                        // this is down
                    } else if (y1 - y0 < 50) {
                        Log.d("daniY", "-");
                        // this is up
                    }
                }

            }

            return true;
        }

    });

这对我有用,这将有助于检测我认为的所有视图上的滚动方向。