How to do interactive animation (translation) with

2019-03-16 20:43发布

问题:

I have some png sequences in Android, that I need to animation their x and y postion translation from the top to the bottom of the screen. While the animation is occurring, I need the objects to receive click events.

I understand this doesn't work really well in Android version before 3.0, since the display of the object is in a different place than the actual object so you don't get the click events mid-animation (which is what I need) since you aren't clicking on the object, only on the display.

I'm doing something like this, and the animation looks fine, but I never get into the click handler:

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

What is the workaround to support interactive animations for devices before 3.0? Is there a custom animation class out there that will use a background thread to animate the x and y position of an object?

--update --- I tried using NineOldAndroid's solution, and the animation looks fine, but I'm not getting the onclick events during the animation. Here is my updated code. So this works fine on ICS, but not on 2.3 Am I doing something wrong? or is the NineOldWorld's solution not actually changing the layout margins under the hood?

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

-- Update #2 --- I also tried the path animation, but during the animation, and after, I'm not getting button click events. Anyone know what I'm doing wrong?

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

回答1:

You're right, the issue is that pre-Honeycomb, only the visual aspect of your animating view is occurring.

This means that in addition to doing the "visual" animation, you also have to set/animate the frame/LayoutParams of the animated view.

For pre-Honeycomb devices, I find http://nineoldandroids.com/ very useful for listening to an animation which you can use for setting the LayoutParams of the view appropriately, but there are other examples as well, such as this one on SO: https://stackoverflow.com/a/3952933/429047



回答2:

This is what I ended up doing, which works pretty well.

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

And here is my class:

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