如何正确地将一个视图从一个坐标点移动到另一个坐标点进行动画?

11
我想要做以下的事情。我有一组带图标的按钮。当用户点击其中一个按钮时,我希望引入一个新的视图,该视图从与所点击的图标相同的坐标开始,然后该新视图将移到屏幕上的其他位置,到达目的地后被移除。
我知道如何创建一个新的视图并将其添加/删除到父RelativeLayout(如果不是RelativeLayout呢?)等等。我不清楚的是如何获取被点击的按钮的绝对坐标(因为它只是另一个父布局中的一个元素),以及如何设置它的坐标并应用动画,然后什么会通知我它已经到达了目的地,以便我可以将其移除?
无法找到如何完成此操作的示例,因此希望有人可以指点我正确的方向。

好的,我已经自己解决了,如果没有人回答,我明天会发布它,供其他人参考。 - Yevgeny Simkin
你也有这方面的教程吗? - ManishSB
3个回答

12

所以,事实证明这比我想象的要容易得多。

我创建了一个全屏的RelativeLayout,在动画发生时只显示它。

我通过以下方式获取我的隐藏按钮的起始位置(在Java中看到这些C风格的编码机制很有趣,这些机制如今已经相当少见):

int fromLoc[] = new int[2];
v.getLocationOnScreen(fromLoc);     
float startX = fromLoc[0];
float startY = fromLoc[1];

现在,我有了起点。

我的终点是屏幕上的一个绝对坐标,您可以按任意方式分配它

然后,我创建了一个小的Animations帮助类,让我可以传入所有坐标、回调和动画的持续时间

    public class Animations {
public Animation fromAtoB(float fromX, float fromY, float toX, float toY, AnimationListener l, int speed){


        Animation fromAtoB = new TranslateAnimation(
                Animation.ABSOLUTE, //from xType
                fromX, 
                Animation.ABSOLUTE, //to xType
                toX, 
                Animation.ABSOLUTE, //from yType 
                fromY, 
                Animation.ABSOLUTE, //to yType 
                toY
                 );

        fromAtoB.setDuration(speed);
        fromAtoB.setInterpolator(new AnticipateOvershootInterpolator(1.0f));


        if(l != null)
            fromAtoB.setAnimationListener(l);               
                return fromAtoB;
    }
}

我们需要一个监听器来告诉我们动画何时完成以清除它

 AnimationListener animL = new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {     
        }

        @Override
        public void onAnimationRepeat(Animation animation) {        
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //this is just a method to delete the ImageView and hide the animation Layout until we need it again.
            clearAnimation();       
        }
    };

最后,我们把所有东西放在一起并按下开始按钮。

int fromLoc[] = new int[2];
    v.getLocationOnScreen(fromLoc);     
    float startX = fromLoc[0];
    float startY = fromLoc[1];      
    RelativeLayout rl = ((RelativeLayout)findViewById(R.id.sticker_animation_layout));
    ImageView sticker = new ImageView(this);

    int stickerId = getStickerIdFromButton(v);
    if(stickerId == 0){
        stickerAnimationPlaying = false;
        return;         
    }

    float destX = 200.0f;//arbitrary place on screen
    float destY = 200.0f;//arbitrary place on screen

    sticker.setBackgroundResource(stickerId);
    sticker.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    rl.addView(sticker);
    Animations anim = new Animations();
    Animation a = anim.fromAtoB(startX, startY, destX, destY, animL,750);
    sticker.setAnimation(a);
    a.startNow();

你有这方面的教程吗?这样会对我有所帮助。 - ManishSB
2
@Real_steel4819,抱歉伙计,我没有教程...只有我在这个答案中写的东西。 - Yevgeny Simkin
getStickerIdFromButton(v); 是什么? - Chad Bingham
如果我没记错的话,@ChadBingham,这是一个帮助方法,允许我查找用户试图拖动的项目的ID,从一个地方到另一个地方。 - Yevgeny Simkin
函数getLocationOnScreen()中的C风格让我想起了pipe() Unix函数。 - trinity420

1
我只是在框架布局的中心位置添加了我的视图,并将我的视图沿x轴和y轴进行了平移。请尝试以下代码:
在FrameLayout上添加ImageView
    imgHeart = new ImageView(getBaseContext());
    imgHeart.setId(R.id.heartImage);
    imgHeart.setImageResource(R.drawable.material_heart_fill_icon);
    imgHeart.setLayoutParams(new FrameLayout.LayoutParams(50, 50, Gravity.CENTER));
    mainFrameLaout.addView(imgHeart);

在图像视图上添加动画。
       imgHeart.animate()
            .scaleXBy(6)
            .scaleYBy(6)
            .setDuration(700)
            .alpha(2)
            .setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    imgHeart.animate()
                            .scaleXBy(-6f).scaleYBy(-6f)
                            .alpha(.1f)
                            .translationX((heigthAndWidth[0] / 2) - minusWidth)
                            .translationY(-((heigthAndWidth[1] / 2) - minusHeight))
                            .setDuration(1000)
                            .setListener(new Animator.AnimatorListener() {
                                @Override
                                public void onAnimationStart(Animator animation) {
                                }

                                @Override
                                public void onAnimationEnd(Animator animation) {
                                // remove image view from framlayout
                                }
                                @Override
                                public void onAnimationCancel(Animator animation) {
                                }

                                @Override
                                public void onAnimationRepeat(Animator animation) {
                                }
                            }).start();
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            }).start();

0

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