如何使用Android进行交互式动画(翻译)



我在Android中有一些png序列,我需要从屏幕顶部到底部对它们的x和y位置转换进行动画处理。当动画发生时,我需要对象来接收点击事件。

我知道这在3.0之前的Android版本中效果并不好,因为对象的显示与实际对象位于不同的位置,所以你不会在动画中期获得点击事件(这正是我所需要的),因为你不是在点击对象,而是在显示上。

我正在做这样的事情,动画看起来很好,但我从来没有进入点击处理程序:

Animation animation = new TranslateAnimation(0, 20,0, 300);
animation.setDuration(1000);
ticket.startAnimation(animation);
ticket.startAnimation(animation);
ticket.setOnClickListener(new OnClickListener() {
    public void onClick(View view) {
            //I don't get into this click event during animation
        view.setVisibility(View.GONE);
    }
});

3.0之前的设备支持交互式动画的解决方法是什么?有没有一个自定义的动画类会使用背景线程来动画对象的x和y位置?

--更新---我尝试使用NineOldAndroid的解决方案,动画看起来很好,但在动画过程中我没有得到onclick事件。这是我更新的代码。所以这在ICS上很好,但在2.3上不行。我做错了什么吗?还是NineOldWorld的解决方案实际上并没有改变引擎盖下的布局边距?

ImageView ticket = new ImageView(myActivity);
            ticket.setImageResource(R.drawable.ticket);
            ticket.setVisibility(View.INVISIBLE);
            ticketHolder.addView(ticket);
            ValueAnimator animation = ObjectAnimator.ofFloat(ticket, "y", 
                    -200f, ticketHolder.getHeight());
            animation.setDuration(3000);
            animation.start();
            animation.setStartDelay(i*1000);
            animationsMap.put(animation, ticket);
            ticket.setOnClickListener(new OnClickListener() {
                public void onClick(View view) {
                    view.setVisibility(View.GONE);
                }
            });
            animation.addListener(new AnimatorListenerAdapter() {
                public void onAnimationEnd(Animator animation) {
//                    tickets.remove(((ObjectAnimator)animation).getTarget());
                    ImageView t = (ImageView) ((ObjectAnimator) animation).getTarget();
                    t.setVisibility(View.GONE);
                    animationsMap.remove(animation);
                    if(animationsMap.size() == 0){
                        ticketsAnimating = false;
                        scrim.setVisibility(View.VISIBLE);
                    }
                }
                @Override
                public void onAnimationStart(Animator animation){
                    ImageView t = (ImageView) ((ObjectAnimator) animation).getTarget();
                    t.setVisibility(View.VISIBLE);
                }
            });

--更新#2---我也尝试了路径动画,但在动画期间和之后,我没有得到按钮单击事件。有人知道我做错了什么吗?

mButton = (Button) findViewById(R.id.delete_me);
mButtonProxy = AnimatorProxy.wrap(mButton);
// Set up the path we're animating along
AnimatorPath path = new AnimatorPath();
path.moveTo(0, 0);
path.lineTo(0, 300);
path.curveTo(100, 0, 300, 900, 400, 500);
// Set up the animation
final ObjectAnimator anim = ObjectAnimator.ofObject(this, "buttonLoc",
        new PathEvaluator(), path.getPoints().toArray());
anim.setDuration(10000);
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("united", "button clicked");
        anim.start();
    }
});

你是对的,问题是在Honeycomb之前,只有动画视图的视觉方面发生了变化。

这意味着,除了执行"视觉"动画外,还必须设置/设置动画视图的帧/LayoutParams的动画。

对于预蜂窝设备,我发现http://nineoldandroids.com/对于收听动画非常有用,您可以使用该动画来适当地设置视图的LayoutParams,但也有其他示例,例如SO上的以下示例:https://stackoverflow.com/a/3952933/429047

这就是我最终所做的,效果非常好。

MyTranslateAnimation animation = new MyTranslateAnimation(ticket, 10, 100, -500, ticketHolder.getHeight());

这是我的课:

public class MyTranslateAnimation extends Animation {
        private float fromXDelta;
        private float fromYDelta;
        private float toXDelta;
        private float toYDelta;
        private View view;
        public MyTranslateAnimation(View view, float fromXDelta,
                float toXDelta, float fromYDelta, float toYDelta) {
            this.view = view;
            this.fromXDelta = fromXDelta;
            this.toXDelta = toXDelta;
            this.fromYDelta = fromYDelta;
            this.toYDelta = toYDelta;
        }
        @Override
        protected void applyTransformation(float interpolatedTime,
                Transformation t) {
            Log.d("united", "time " + interpolatedTime);
            float newX = (toXDelta - fromXDelta) * interpolatedTime;
            float newY = (toYDelta - fromYDelta) * interpolatedTime;
            LayoutParams p = (LayoutParams) view.getLayoutParams();
            p.leftMargin = (int) newX;
            p.topMargin = (int) newY;
            if (interpolatedTime > 0.0 && view.getVisibility() == View.GONE) {
                view.setVisibility(View.VISIBLE);
            }
            view.requestLayout();
        }
    }

最新更新