中断转换动画与再掀 [英] Interrupt translate animation and start another

查看:198
本文介绍了中断转换动画与再掀的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我需要根据目前的重点子视图调整视图位置的应用程序(它与可聚焦的项目列表,当前焦点项目必须是在该中心的屏幕 - 用于从电视机遥控器控制电视的应用程序)。
位置必须与动画进行调整。
我得到它的工作只有一个问题:如果用户改变集中在动画完成之前(快速水龙头上按钮两次)下一个动画开始,跳 - 它从同一位置开始象第一个

I have an application where I need to adjust view position according to current focused subview (it's a list with focusable items, current focused item must be in the center of the screen - used for a tv application controlled from tv remote).
Position must be adjusted with animation.
I got it working with just one problem: if the user changes focus before the animation is complete (quickly taps "up" button twice) next animation starts with "jump" - it starts from the same position as did the first one.

所以我尝试做的是我取消previous动画,并开始另一个,但随后新的动画开始从第一个动画开始点在哪里,这样用户就可以看到动画中的一个非常明显的跳跃,这看起来真的太可怕了。

So what I try to do is I cancel previous animation and start another, but then new animation starts from the point where first animation was started, so user can see a very obvious jumps in the animation, which look really awful.

这里的code:

@Override
public void requestChildFocus(final View child, final View focused) {
    super.requestChildFocus(child, focused);

    //this test code included for explanation
    Rect r = new Rect();
    child.getDrawingRect(r); //this will return view's position ignoring animation state
    Rect r2 = new Rect();
    child.getGlobalVisibleRect(r2); //as will this one too
    Log.d("Top: " + child.getTop() + "; Drawing rect: " +  r.toString() + "; global visible rect: " + r2.toString()); 
    //all of this methods will ignore changes that were made 
    //by animation object - they'll return numbers from LayoutParam

    //calculate current position inside view and position to move to
    //cursorOffset - is the "center" of the screen
    final int currentPosition = child.getTop();
    final int requaredPosition = cursorOffset - focused.getTop();

    //cancel current running animation - layout params will not change
    //if i do change layout params when cancelling animation, it looks even worse
    //because of jumping back list jumps forward
    if (currentAnimation != null) {
        Animation animation = currentAnimation;
        currentAnimation = null;
        animation.cancel();
    }

    //just a regular translate animation
    TranslateAnimation animation = new TranslateAnimation(0, 0, 0, requaredPosition - currentPosition);
    animation.setDuration(300);
    animation.setFillEnabled(true);
    animation.setFillBefore(true);
    animation.setAnimationListener(new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            currentAnimation = animation;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            if (animation == currentAnimation) {
                //change layout params if animation finished running (wasn't cancelled)
                RelativeLayout.LayoutParams params = (LayoutParams) child.getLayoutParams();
                params.setMargins(0, requaredPosition, 0, 0);
                child.setLayoutParams(params);
            }
        }
    });
    child.startAnimation(animation);
}

所以一定要的问题是:我怎么能开始从点previous翻译动画留在(假设它被取消)翻译动画
或者,在simplier的话,我怎么能确定当前可见的视图的矩形?

So must question is: how can I start translate animation from the point where previous translate animation left on (assuming that it was cancelled)?
Or, in a simplier words, how can I determine current visible rect of a view?

推荐答案

显然,你不能让当前视图的位置,但你可以得到当前动画状态。
所以,你可以得到当前y做这个偏移:

Apparently you can't get current view position, but you can get current animation state.
So you can get current y offset by doing this:

Transformation transformation = new Transformation();
float[] matrix = new float[9];
currentAnimation.getTransformation(AnimationUtils.currentAnimationTimeMillis(), transformation);
transformation.getMatrix().getValues(matrix);
float y = matrix[Matrix.MTRANS_Y];

这就是我如何能够从那里我留下的一点恰好抵消一个动画,并开始另一个。如果有人关心,继承人的完整的code:

And that's how I was able to cancel one animation and start another one exactly from the point where I left of. If anyone cares, heres the complete code:

private Animation currentAnimation;
private float[] matrix = new float[9];
private Transformation transformation = new Transformation();

@Override
public void requestChildFocus(final View child, final View focused) {
    super.requestChildFocus(child, focused);

    final int currentPosition;

    if (currentAnimation != null) {
        currentAnimation.getTransformation(AnimationUtils.currentAnimationTimeMillis(), transformation);
        transformation.getMatrix().getValues(matrix);
        float y = matrix[Matrix.MTRANS_Y];

        RelativeLayout.LayoutParams params = (LayoutParams) child.getLayoutParams();
        params.topMargin += y;
        //child.getTop() will return wrong position until layout actually happens, 
        //so I use params.topMargin as a current position in case I need to cancel
        currentPosition = params.topMargin;
        child.requestLayout();

        currentAnimation.setAnimationListener(null);
        currentAnimation.cancel();
        currentAnimation = null;
    } else {
        currentPosition = child.getTop();
    }

    final int requaredPosition = cursorOffset - focused.getTop();

    TranslateAnimation animation = new TranslateAnimation(0, 0, 0, requaredPosition - currentPosition);
    animation.setDuration(300);
    animation.setFillEnabled(true);
    animation.setFillBefore(true);
    animation.setAnimationListener(new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            currentAnimation = animation;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            if (animation == currentAnimation) {
                RelativeLayout.LayoutParams params = (LayoutParams) child.getLayoutParams();
                params.setMargins(0, requaredPosition, 0, 0);
                child.requestLayout();
            }
            currentAnimation = null;
        }
    });
    child.startAnimation(animation);
}

希望有人认为这是有用的。

Hope somebody finds this useful.

这篇关于中断转换动画与再掀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆