android开发通过Scroller实现过渡滑动效果操作示例
程序员文章站
2022-03-04 17:01:33
本文实例讲述了android开发通过scroller实现过渡滑动效果。分享给大家供大家参考,具体如下:
主要介绍一下scroller这个类,它可以实现过渡滑动的效果,使滑动看起来不是...
本文实例讲述了android开发通过scroller实现过渡滑动效果。分享给大家供大家参考,具体如下:
主要介绍一下scroller这个类,它可以实现过渡滑动的效果,使滑动看起来不是那么生硬,当然它用大量的重绘来实现,invalidate();通过源码看:
看构造方法
/** * create a scroller with the default duration and interpolator. */ public scroller(context context) { this(context, null); } /** * create a scroller with the specified interpolator. if the interpolator is * null, the default (viscous) interpolator will be used. "flywheel" behavior will * be in effect for apps targeting honeycomb or newer. */ public scroller(context context, interpolator interpolator) { this(context, interpolator, context.getapplicationinfo().targetsdkversion >= build.version_codes.honeycomb); } /** * create a scroller with the specified interpolator. if the interpolator is * null, the default (viscous) interpolator will be used. specify whether or * not to support progressive "flywheel" behavior in flinging. */ public scroller(context context, interpolator interpolator, boolean flywheel) { mfinished = true; if (interpolator == null) { minterpolator = new viscousfluidinterpolator(); } else { minterpolator = interpolator; } mppi = context.getresources().getdisplaymetrics().density * 160.0f; mdeceleration = computedeceleration(viewconfiguration.getscrollfriction()); mflywheel = flywheel; mphysicalcoeff = computedeceleration(0.84f); // look and feel tuning }
我们用默认的就行,传个context就行了,其他的什么差值器,先不管了
然后调用startscroll,传递我们歧视滑动位置和滑动的偏移量,还有可选的默认持续时间,默认为250毫秒
这个方法是用来赋值的,接下来会调用invalidate()进行重新绘制,然后就会ondraw(),这时候会调用
computescroll()这个方法,我们重写这个方法,computescrolloffset()是判断动画有没有结束的一个方法,没结束的时候,我们根据滑动的偏移位置进行移动也就是scrollto到scroller的当前位置,再次调用invalidate(),由此无数的重回进行拼接形成了平滑的滑动
/** * call this when you want to know the new location. if it returns true, * the animation is not yet finished. */ public boolean computescrolloffset() { if (mfinished) { return false; } int timepassed = (int)(animationutils.currentanimationtimemillis() - mstarttime); if (timepassed < mduration) { switch (mmode) { case scroll_mode: final float x = minterpolator.getinterpolation(timepassed * mdurationreciprocal); mcurrx = mstartx + math.round(x * mdeltax); mcurry = mstarty + math.round(x * mdeltay); break; case fling_mode: final float t = (float) timepassed / mduration; final int index = (int) (nb_samples * t); float distancecoef = 1.f; float velocitycoef = 0.f; if (index < nb_samples) { final float t_inf = (float) index / nb_samples; final float t_sup = (float) (index + 1) / nb_samples; final float d_inf = spline_position[index]; final float d_sup = spline_position[index + 1]; velocitycoef = (d_sup - d_inf) / (t_sup - t_inf); distancecoef = d_inf + (t - t_inf) * velocitycoef; } mcurrvelocity = velocitycoef * mdistance / mduration * 1000.0f; mcurrx = mstartx + math.round(distancecoef * (mfinalx - mstartx)); // pin to mminx <= mcurrx <= mmaxx mcurrx = math.min(mcurrx, mmaxx); mcurrx = math.max(mcurrx, mminx); mcurry = mstarty + math.round(distancecoef * (mfinaly - mstarty)); // pin to mminy <= mcurry <= mmaxy mcurry = math.min(mcurry, mmaxy); mcurry = math.max(mcurry, mminy); if (mcurrx == mfinalx && mcurry == mfinaly) { mfinished = true; } break; } } else { mcurrx = mfinalx; mcurry = mfinaly; mfinished = true; } return true; }
public void startscroll(int startx, int starty, int dx, int dy) { startscroll(startx, starty, dx, dy, default_duration); } public void startscroll(int startx, int starty, int dx, int dy, int duration) { mmode = scroll_mode; mfinished = false; mduration = duration; mstarttime = animationutils.currentanimationtimemillis(); mstartx = startx; mstarty = starty; mfinalx = startx + dx; mfinaly = starty + dy; mdeltax = dx; mdeltay = dy; mdurationreciprocal = 1.0f / (float) mduration; }
public class movefreeview extends view{ private int movedx; private int movedy; private scroller mscroller; public movefreeview(context context) { super(context); } public movefreeview(context context, @nullable attributeset attrs) { super(context, attrs); mscroller = new scroller(context); } public movefreeview(context context, @nullable attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } @override public boolean ontouchevent(motionevent event) { //获取触摸点到边界坐标 int x = (int) event.getx(); int y = (int) event.gety(); switch (event.getaction()){ case motionevent.action_down: movedx = x; movedy = y; break; case motionevent.action_move: int offsetx = x-movedx; int offsety = y-movedy; layout(getleft()+offsetx,gettop()+offsety,getright()+offsetx,getbottom()+offsety); break; } return super.ontouchevent(event); } //供外界调用通过传递x,y的的滑动距离 public void smoothscrollto(int destinyx,int destinyy){ //向右侧,下方滑动,请传递负值 int scrollx = getscrollx(); int scrolly = getscrolly(); int delta = destinyx - scrollx; int deltay = destinyy - scrolly; mscroller.startscroll(scrollx,scrolly,delta,deltay,5000); invalidate(); } @override public void computescroll() { super.computescroll(); //true则表示滑动未结束 if (mscroller.computescrolloffset()){ ((view) getparent()).scrollto(mscroller.getcurrx(),mscroller.getcurry()); invalidate(); } } }
private movefreeview button; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); button = (movefreeview) findviewbyid(r.id.custon); button.smoothscrollto(-400,-300); // button.startanimation(animationutils.loadanimation(this,r.anim.translate)); // objectanimator animtor1 = objectanimator.offloat(button, "translationx", 0, 300); // objectanimator animtor2 = objectanimator.offloat(button, "translationy", 0, 300); // objectanimator animator3 = objectanimator.offloat(button,"rotationx",0.0f,360f); // objectanimator animator4 = objectanimator.offloat(button,"scalex",1.5f,0.5f); // animatorset set= new animatorset(); // set.setduration(5000); // set.playtogether(animtor1,animtor2,animator3,animator4); // set.addlistener(new animator.animatorlistener() { // @override // public void onanimationstart(animator animator) { // // } // // @override // public void onanimationend(animator animator) { // //动画结束时做一些事情 // } // // @override // public void onanimationcancel(animator animator) { // // } // // @override // public void onanimationrepeat(animator animator) { // // } // }); // set.start(); } }