一聚教程网:一个值得你收藏的教程网站

热门教程

Android界面上拉下拉的回弹效果实例代码

时间:2022-06-25 23:28:25 编辑:袖梨 来源:一聚教程网

 

 代码如下复制代码

publicclassMyScrollViewextendsScrollView {

  privateView childView;

  publicMyScrollView(Context context) {

    super(context);

  }

  publicMyScrollView(Context context, AttributeSet attrs) {

    super(context, attrs);

  }

  publicMyScrollView(Context context, AttributeSet attrs,intdefStyleAttr) {

    super(context, attrs, defStyleAttr);

  }

//  @Override

//  protected void onLayout(boolean changed, int l, int t, int r, int b) {

//    super.onLayout(changed, l, t, r, b);

//  }

  //获取子视图

  @Override

  protectedvoidonFinishInflate() {

    super.onFinishInflate();

    if(getChildCount() >0) {

      childView = getChildAt(0);

    }

  }

  privateintlastY;//上一次y轴方向操作的坐标位置

  privateRect normal =newRect();//用于记录临界状态的左、上、右、下

  privatebooleanisFinishAnimation =true;//是否动画结束

  privateintlastX, downX, downY;

  //拦截:实现父视图对子视图的拦截

  //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败

  @Override

  publicbooleanonInterceptTouchEvent(MotionEvent ev) {

    booleanisIntercept =false;

    inteventX = (int) ev.getX();

    inteventY = (int) ev.getY();

    switch(ev.getAction()) {

      caseMotionEvent.ACTION_DOWN:

        lastX = downX = eventX;

        lastY = downY = eventY;

        break;

      caseMotionEvent.ACTION_MOVE:

        //获取水平和垂直方向的移动距离

        intabsX = Math.abs(eventX - downX);

        intabsY = Math.abs(eventY - downY);

        if(absY > absX && absY >= UIUtils.dp2px(10)){

          isIntercept =true;//执行拦截

        }

        lastX = eventX;

        lastY = eventY;

        break;

    }

    returnisIntercept;

  }

  @Override

  publicbooleanonTouchEvent(MotionEvent ev) {

    if(childView ==null|| !isFinishAnimation) {

      returnsuper.onTouchEvent(ev);

    }

    inteventY = (int) ev.getY();//获取当前的y轴坐标

    switch(ev.getAction()) {

      caseMotionEvent.ACTION_DOWN:

        lastY = eventY;

        break;

      caseMotionEvent.ACTION_MOVE:

        intdy = eventY - lastY;//微小的移动量

        if(isNeedMove()) {

          if(normal.isEmpty()) {

            //记录了childView的临界状态的左、上、右、下

            normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());

          }

          //重新布局

          childView.layout(childView.getLeft(),  childView.getTop() + dy /2, childView.getRight(), childView.getBottom()  + dy /2);

        }

        lastY = eventY;//重新赋值

        break;

      caseMotionEvent.ACTION_UP:

        if(isNeedAnimation()) {

          //使用平移动画

          inttranslateY = childView.getBottom() - normal.bottom;

          TranslateAnimation translateAnimation =newTranslateAnimation(0,0,0, -translateY);

          translateAnimation.setDuration(200);

//        translateAnimation.setFillAfter(true);//停留在最终位置上

          translateAnimation.setAnimationListener(newAnimation.AnimationListener() {

            @Override

            publicvoidonAnimationStart(Animation animation) {

              isFinishAnimation =false;

            }

            @Override

            publicvoidonAnimationEnd(Animation animation) {

              isFinishAnimation =true;

              childView.clearAnimation();//清除动画

              //重新布局

              childView.layout(normal.left, normal.top, normal.right, normal.bottom);

              //清除normal的数据

              normal.setEmpty();

            }

            @Override

            publicvoidonAnimationRepeat(Animation animation) {

            }

          });

          //启动动画

          childView.startAnimation(translateAnimation);

        }

        break;

    }

    returnsuper.onTouchEvent(ev);

  }

  //判断是否需要执行平移动画

  privatebooleanisNeedAnimation() {

    return!normal.isEmpty();

  }

  privatebooleanisNeedMove() {

    intchildMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度

    intscrollViewMeasuredHeight =this.getMeasuredHeight();//获取布局的高度

    Log.e("TAG","childMeasuredHeight = "+ childMeasuredHeight);

    Log.e("TAG","scrollViewMeasuredHeight = "+ scrollViewMeasuredHeight);

    intdy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0

    intscrollY =this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -)

    if(scrollY <=0|| scrolly="">= dy) {

      returntrue;//按照我们自定义的MyScrollView的方式处理

    }

    //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理

    returnfalse;

  }

}

 

热门栏目