本文实例讲述了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();
}
}
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!