如何在Android上进行交互式动画制作

3
我有一些在Android中的png序列,我需要使它们在屏幕从上到下平移x和y位置。在动画发生时,我需要这些对象接收点击事件。
我知道在Android 3.0之前的版本中,这并不是很好使,因为对象的“显示”与实际对象所在的位置不同,所以你无法在动画进行时获得点击事件(这正是我需要的),因为你只是在点击显示而不是对象本身。
我正在做类似于这样的事情,动画看起来很好,但我从未进入过点击处理程序:
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();
    }
});
2个回答

4

你说得对,问题在于在Honeycomb之前,只有你的动画视图的可见部分发生了变化。

这意味着除了进行“可见”动画之外,您还需要设置/动画化动画视图的frame/LayoutParams。

对于Honeycomb之前的设备,我发现http://nineoldandroids.com/非常有用,可以用于监听动画,您可以使用它来适当地设置视图的LayoutParams,但也有其他示例,例如Stack Overflow上的这个示例:https://dev59.com/wXE85IYBdhLWcg3wvGKm#3952933


我更新了我的回答,你能看出我错在哪里吗?为什么我无法获得点击事件,这是与noneoldandroid的解决方案有关的问题。 - b-ryce
13
NineOldAndroids仅提供一个统一的API。不幸的是,它遇到了与使用本机视图动画时相同的限制。如果动画移动屏幕上的某些内容,并且您希望该内容仍然可点击,则需要在动画完成后使用其“LayoutParams”物理移动对象。这很糟糕,但这就是我们所拥有的。 - Jake Wharton
糟糕。这就是我想的。谢谢Jake。我会开始研究如何正确地做这件事。如果你知道有任何示例可以做到这一点,我很乐意看看。 - b-ryce
@Mo Kargas,FYI,看起来这不是事实:“对于Honeycomb之前的设备,我发现http://nineoldandroids.com/非常有用,可以监听动画并适当地设置视图的LayoutParams”。根据其创建者Jake Wharton的说法,它不会设置布局参数。 - b-ryce
B-ryce - 我知道 Nine Old Androids 并不处理实际的布局修改,我对此点表达不清深感抱歉。但它提供了一个很好的 API 来监听动画 - 是的,你仍然需要手动处理 LayoutParam 的修改,就像 Jake 所提到的那样,但你可以使用 Nine 提供的监听器来完成这个过程。 - Mo Kargas
@JakeWharton 我尝试了你的解决方案,它起作用了,但还不完美,在onAnimationEnd()中添加了setLayoutParams()后,动画效果没有显示,代码片段如下我的代码,你能否帮我找出问题所在,谢谢。 - Weibo

1

这就是我最终做的,效果相当不错。

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();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接