上一篇讲到view的invalidate方法可以通知ui进行重绘操作,如果在invalidate之前更改了数据,那么就能导致UI的变化,但是这种变化的用户体验很差,我们需要控件能够弹性的,渐进式滑动。实现的方式有很多种,但重心思想是动作的拆分,将一整个动作分成若干小动作并在一个时间段内完成。-----参考自任玉刚《安卓开发艺术探索》
实现滑动的方式:
1:layout方法,view进行绘制时,会调用onlayout方法来设置显示的位置,我们可以修改view的边界属性来控制view的坐标.具体做法就是down时记录坐标,move时计算偏移量,然后layout(getLeft()+offsetX............)四个属性都加上偏移量。
2:offsetLeftAndRight()与offsetTopAndBottom().相当于对左右,上下移动的API的封装
offsetLetAndRight(offsetX);
offsetUpAndBottom(offsetY);
3:layoutParams
void scroll(int offsetX,int offsetY){
LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin=getLeft()+offsetX;
layoutParams.topMargin=getTop()+offsetY;
setLayoutParams(layoutParams);
}
4:srcollto 和scrollBy
两者区别:scrollTo表移动到某坐标点,scrollBy表移动该向量。
scroll to 和scrollBy移动的是view的内容。所以要想移动view自身,需要其父控件srcollTo 和scrollBy.
5:scroller Scroller类能帮助我们使得空间平滑移动。
Scroller mScroller=new Scroller(getContext()); private void smoothScrollTo(int destX,int destY){ int scrollX=getScrollX(); int deltaX=destX-scrollX; mScroller.startScroll(scrollX,0,deltaX,0,1000); invalidate(); } @Override public void computeScroll() { super.computeScroll(); //判断Scroller是否执行完毕 if(mScroller.computeScrollOffset()){ ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); invalidate(); } }
startScroll 调用invalidate方法,导致view重绘,draw方法中调用computeScroll方法,computeScroll方法会向scroller获取当前的scrollX,scrollY,然后通过scrollTo滑动。接着又调用invalidate方法导致再次重绘,直到滑动结束。