仿qq写一个可以来回弹的ScrollView.

只需要重写ScrollView:

publicclassMyScrollViewextendsScrollView{//y方向上当前触摸点的前一次记录位置privateintpreviousY=0;//y方向上的触摸点的起始记录位置privateintstartY=0;//y方向上的触摸点当前记录位置privateintcurrentY=0;//y方向上两次移动间移动的相对距离privateintdeltaY=0;//第一个子视图privateViewchildView;//用于记录childView的初始位置privateRecttopRect=newRect();publicMyScrollView(Contextcontext){super(context);}publicMyScrollView(Contextcontext,AttributeSetattrs){super(context,attrs);}publicMyScrollView(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);}@SuppressLint("MissingSuperCall")@OverrideprotectedvoidonFinishInflate(){if(getChildCount()>0){childView=getChildAt(0);}}@OverridepublicbooleandispatchTouchEvent(MotionEventevent){if(null==childView){returnsuper.dispatchTouchEvent(event);}switch(event.getAction()){caseMotionEvent.ACTION_DOWN:startY=(int)event.getY();previousY=startY;break;caseMotionEvent.ACTION_MOVE:currentY=(int)event.getY();deltaY=previousY-currentY;previousY=currentY;if(0==getScrollY()||childView.getMeasuredHeight()-getHeight()<=getScrollY()){//记录childView的初始位置if(topRect.isEmpty()){topRect.set(childView.getLeft(),childView.getTop(),childView.getRight(),childView.getBottom());}//更新childView的位置childView.layout(childView.getLeft(),childView.getTop()-deltaY/3,childView.getRight(),childView.getBottom()-deltaY/3);}break;caseMotionEvent.ACTION_UP:if(!topRect.isEmpty()){upDownMoveAnimation();//子控件回到初始位置childView.layout(topRect.left,topRect.top,topRect.right,topRect.bottom);}startY=0;currentY=0;topRect.setEmpty();break;default:break;}returnsuper.dispatchTouchEvent(event);}//初始化上下回弹的动画效果privatevoidupDownMoveAnimation(){TranslateAnimationanimation=newTranslateAnimation(0.0f,0.0f,childView.getTop(),topRect.top);animation.setDuration(100);animation.setInterpolator(newAccelerateInterpolator());childView.setAnimation(animation);}}

然后想在哪用直接布局就行了。这种重写方法是不会和子控件的点击事件起冲突的。