`
flyouting
  • 浏览: 14495 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于ListView的弹性滑动

阅读更多
    最近项目中用到了弹性滑动,但是这个弹性滑动只有在2.3之后才有了功能函数,在2.2以及之前的版本中,只有自己去实现了。
    查了一下网上的资源,貌似没有提供出来一个具体的方式来实现。看到一个牛人写的一个软件中实现了弹性滑动,查了查源码,然后看了看ListView的源码,然后自己搞了一下,实现了弹性滑动。
    基本思路就是得到出当前的可显示的item的位置,然后判断出否是越界,这里的越界就是是否有过度的滑动。如果有的话,就利用ScrollTo()这个方法,先把控件滑动到手势触摸事件的位置,当触摸事件结束时,滑动到屏幕顶端,或者末端。
    首先是自定义一个类,继承ListView,然后在其中加入手势的事件模型。在处理touch事件时将事件交给手势listener来处理。并且返回父类的处理结果。
   
public class BouncyListView extends ListView {

    private Context context;
    /*
     * Slide over so that cross-border
     */
    private boolean outBound = false;
    private int distance;
    private int firstOut;

    public BouncyListView(Context context) {
        super(context);
        this.context = context;
    }

    public BouncyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public BouncyListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    GestureDetector mGestureDetector = new GestureDetector(context,
            new GestureDetector.OnGestureListener() {

                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return false;
                }

                @Override
                public void onShowPress(MotionEvent e) {

                }

                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2,
                        float distanceX, float distanceY) {
                    int firstPos = getFirstVisiblePosition();
                    int lastPos = getLastVisiblePosition();
                    int itemCount = getCount();
                    //outbound Top
                    if (outBound && firstPos != 0 && lastPos != (itemCount - 1)) {
                        scrollTo(0, 0);
                        return false;
                    }
                    View firstView = getChildAt(firstPos);
                    if (!outBound)
                        firstOut = (int) e2.getRawY();
                    if (firstView != null
                            && (outBound || (firstPos == 0
                                    && firstView.getTop() == 0 && distanceY < 0))) {
                        //Record the length of each slide
                        distance = firstOut - (int) e2.getRawY();
                        scrollTo(0, distance/2);
                        return true;
                    }
                    //outbound Bottom
                     

                    return false;
                }

                @Override
                public void onLongPress(MotionEvent e) {

                }

                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2,
                        float velocityX, float velocityY) {
                    return false;
                }

                @Override
                public boolean onDown(MotionEvent e) {
                    return false;
                }
            });

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        int act = event.getAction();
        if ((act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_CANCEL)
                && outBound) {
            outBound = false;
            //scroll back
        }
        if (!mGestureDetector.onTouchEvent(event)) {
            outBound = false;
        } else {
            outBound = true;
        }
        return super.dispatchTouchEvent(event);
    }

}


    实现过度滑动,item跟随手势的代码是这一段:
int firstPos = getFirstVisiblePosition();
					int lastPos = getLastVisiblePosition();
					int itemCount = getCount();

					if (outBound && firstPos != 0
							&& lastPos != (itemCount - 1)) {
						scrollTo(0, 0);
						return false;
					}
					View firstView = getChildAt(firstPos);

					if (!outBound)
						firstOut = (int) e2.getRawY();
					if (firstView != null && (outBound || 
							(firstPos == 0 && firstView.getTop() == 0 && distanceY < 0))){
						
						distance = firstOut - (int) e2.getRawY();
						scrollTo(0, distance/2);
						return true;
					}


    scrollTo(0, distance/2);使得item只是过度滑动你所滑动距离的一半,这样更美观。
   
    而实现弹性滑动的基本思路就是滑动回去加个时间。
    代码如下:
   
Rect rect = new Rect();
			getLocalVisibleRect(rect);
			TranslateAnimation am = new TranslateAnimation( 0, 0, -rect.top, 0);
			am.setDuration(300);
			startAnimation(am);
                        scrollTo(0, 0);

    这个代码是从项目中摘出的。只有上面的弹性滑动,下边部分其实一样。
    显示效果如下


    看别人的代码往往会给自己带来一些思路,然后自己去研究,以上的思路可以应用与Gridview,我这里实现Gridview的弹性滑动是没有问题的。我目前遇到的一个问题就是ScrollView的弹性滑动问题。看了很长时间的ScrollView的源码,但是没有太好的思路,主要是在显示部分的坐标拿不到,不像ListView里可以通过getFirstVisiblePosition()这样一个方法来拿到item的位置,继而拿到item,ScrollView中只有一个子控件。他的滑动实现貌似跟ListView,Gridview这些采用Adapter的不一样。在研究中,哪位兄台如果知道其中原来,还请告知一声。
    

    

  • 大小: 28 KB
4
6
分享到:
评论
3 楼 追忆的风 2012-10-11  
没有源码等于没用
2 楼 hejiehejie 2012-06-15  
兄弟 等好久了,希望能发我一份 源码  QQ 1017191318 感激不尽
1 楼 zhfally520 2011-08-09  

                    if  (outBound && firstPos !=  0  && lastPos != (itemCount -  1 )) {  
                        scrollTo(0 ,  0 );  
                        return   false ;  
                    }  

相关推荐

Global site tag (gtag.js) - Google Analytics