Android:滚动动画?
我是Android开发的新手,我只想了解一下Scroller小部件(Android.widget.Scroller)。它如何设置视图的动画?是否可以访问动画对象(如果存在)?如果是,怎么做?我读过源代码,但找不到任何线索,或者我太新了 我只是想在滚动器完成滚动后做一些操作,比如Android:滚动动画?,android,animation,scroll,scroller,Android,Animation,Scroll,Scroller,我是Android开发的新手,我只想了解一下Scroller小部件(Android.widget.Scroller)。它如何设置视图的动画?是否可以访问动画对象(如果存在)?如果是,怎么做?我读过源代码,但找不到任何线索,或者我太新了 我只是想在滚动器完成滚动后做一些操作,比如 m_scroller.getAnimation().setAnimationListener(...); Scroller小部件实际上并没有为您做很多工作。它不触发任何回调,也不设置任何动画,它只响应各种方法调用 那有
m_scroller.getAnimation().setAnimationListener(...);
Scroller小部件实际上并没有为您做很多工作。它不触发任何回调,也不设置任何动画,它只响应各种方法调用 那有什么好处呢?好吧,它为你做了所有的计算,比如说一次放纵,这很方便。因此,您通常要做的是创建一个Runnable,反复询问滚动条,“我的滚动位置现在应该是什么?我们是否完成了投掷?”然后将该Runnable重新发布到处理程序上(通常在视图上),直到投掷完成 下面是我正在研究的一个片段的示例:
private class Flinger implements Runnable {
private final Scroller scroller;
private int lastX = 0;
Flinger() {
scroller = new Scroller(getActivity());
}
void start(int initialVelocity) {
int initialX = scrollingView.getScrollX();
int maxX = Integer.MAX_VALUE; // or some appropriate max value in your code
scroller.fling(initialX, 0, initialVelocity, 0, 0, maxX, 0, 10);
Log.i(TAG, "starting fling at " + initialX + ", velocity is " + initialVelocity + "");
lastX = initialX;
getView().post(this);
}
public void run() {
if (scroller.isFinished()) {
Log.i(TAG, "scroller is finished, done with fling");
return;
}
boolean more = scroller.computeScrollOffset();
int x = scroller.getCurrX();
int diff = lastX - x;
if (diff != 0) {
scrollingView.scrollBy(diff, 0);
lastX = x;
}
if (more) {
getView().post(this);
}
}
boolean isFlinging() {
return !scroller.isFinished();
}
void forceFinished() {
if (!scroller.isFinished()) {
scroller.forceFinished(true);
}
}
}
使用Scroller.startScroll的详细信息应该类似。上面的回答很好。Scroller#startScroll(…)的工作方式确实相同 例如,自定义滚动文本视图的源位于: 使用TextView#setScroller(滚动条)在TextView上设置滚动条 SDK的TextView的源代码位于: 显示TextView#setScroller(Scroller)设置一个类字段,该字段在调用Scroller#scrollTo(int,int,int,int)的情况下使用
bringPointIntoView()调整mScrollX和mScrollY(使用一些SDK碎片代码),然后调用invalidate()。所有这一切的要点是,mScrollX和mScrollY在onPreDraw(…)等方法中被用来影响视图中绘制内容的位置。我们可以扩展
滚动器
类,然后在computeScrollOffset()之后截取相应的动画启动方法来标记已启动的动画返回false,这意味着动画完成的值,我们通过侦听器通知调用方:
public class ScrollerImpl extends Scroller {
...Constructor...
private boolean mIsStarted;
private OnFinishListener mOnFinishListener;
@Override
public boolean computeScrollOffset() {
boolean result = super.computeScrollOffset();
if (!result && mIsStarted) {
try { // Don't let any exception impact the scroll animation.
mOnFinishListener.onFinish();
} catch (Exception e) {}
mIsStarted = false;
}
return result;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy);
mIsStarted = true;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, duration);
mIsStarted = true;
}
@Override
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) {
super.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
mIsStarted = true;
}
public void setOnFinishListener(OnFinishListener onFinishListener) {
mOnFinishListener = onFinishListener;
}
public static interface OnFinishListener {
void onFinish();
}
}
正如Bill Phillips所说,Scroller只是一个帮助计算滚动位置的Android SDK类。我这里有一个完整的工作示例:
public class SimpleScrollableView extends TextView {
private Scroller mScrollEventChecker;
private int mLastFlingY;
private float mLastY;
private float mDeltaY;
public SimpleScrollableView(Context context) {
this(context, null, 0);
}
public SimpleScrollableView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SimpleScrollableView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mScrollEventChecker != null && !mScrollEventChecker.isFinished()) {
return super.onTouchEvent(event);
}
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
int movingDelta = (int) (event.getY() - mLastY);
mDeltaY += movingDelta;
offsetTopAndBottom(movingDelta);
invalidate();
return true;
case MotionEvent.ACTION_UP:
mScrollEventChecker = new Scroller(getContext());
mScrollEventChecker.startScroll(0, 0, 0, (int) -mDeltaY, 1000);
post(new Runnable() {
@Override
public void run() {
if (mScrollEventChecker.computeScrollOffset()) {
int curY = mScrollEventChecker.getCurrY();
int delta = curY - mLastFlingY;
offsetTopAndBottom(delta); // this is the method make this view move
invalidate();
mLastFlingY = curY;
post(this);
} else {
mLastFlingY = 0;
mDeltaY = 0;
}
}
});
return super.onTouchEvent(event);
}
return super.onTouchEvent(event);
}
}
用户释放视图后,上面的演示自定义视图将回滚到原始位置。当用户释放视图时,就会调用startScroll()方法,我们可以知道每条消息的距离值应该是多少
完整的工作示例:我明白了。因此,您为滚动条实现了一种侦听器线程。美好的谢谢!:)您的
isFlinging()方法不应该返回!scroller.isFinished()
?要么将其重命名为isFinished()
。很好的例子:)是的,它应该。固定的。谢谢希望有人能给我解释一下。在我问这个问题差不多两年后,我想你也可以创建一个子类,它接受一个委托,并定期调用该委托上的某些方法,即onScrollFinished()或onOverscroll(),在我看来,这比一直轮询滚动条要好@比尔菲利普斯:不过你在这件事上确实帮了我的忙。:)前面的实现使用一个线程来轮询滚动器的滚动位置。在扩展Scroller的实现中,如何从视图中轮询ScrollerImpl以获得滚动位置的更改?对不起,我不太清楚您的问题,您想知道如何使用ScrollerImpl
?@carignan.boy在这种情况下您不轮询。您要做的是设置ScrollerImpl OnFinishListener,然后等待调用onFinish()方法。这样做比投票要好得多;这正是我在接受答案的评论中的意思。