当前位置:首页 > 行业动态 > 正文

安卓开发动画点击移动

安卓点击触发视图移动动画实现方案

核心动画类型选择

动画类型 适用场景 特点
View Animation 简单平移/缩放/旋转动画 仅修改渲染效果,不改变视图实际属性
Property Animator 复杂属性动画(含坐标变换) 直接修改视图属性,支持更精确的动画控制

实现步骤详解(以Property Animator为例)

  1. 获取目标视图引用

    View targetView = findViewById(R.id.movable_view);
  2. 创建点击事件监听器

    targetView.setOnClickListener(v -> {
        // 触发动画逻辑
    });
  3. 构建坐标动画

    安卓开发动画点击移动  第1张

    // 获取当前坐标(需转换为float类型)
    float startX = targetView.getX();
    float startY = targetView.getY();
    // 设置目标坐标(示例:向右移动200px,向下移动100px)
    float endX = startX + 200;
    float endY = startY + 100;
    // 创建动画对象
    ObjectAnimator translateX = ObjectAnimator.ofFloat(targetView, "x", startX, endX);
    ObjectAnimator translateY = ObjectAnimator.ofFloat(targetView, "y", startY, endY);
    // 组合动画
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.playTogether(translateX, translateY);
  4. 配置动画参数

    animatorSet.setDuration(500); // 持续时间500ms
    animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); // 加速减速插值器
    animatorSet.start(); // 启动动画

关键注意事项

  1. 坐标系统转换

    • view.getX()/getY()返回相对父布局的坐标
    • 需要确保父布局为RelativeLayoutConstraintLayout等支持自由定位的布局
  2. 动画结束后状态保持

    animatorSet.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            // 可选:将最终坐标写入布局参数(仅当需要持久化位置时)
            MarginLayoutParams params = (MarginLayoutParams) targetView.getLayoutParams();
            params.leftMargin = (int)endX;
            params.topMargin = (int)endY;
            targetView.setLayoutParams(params);
        }
    });
  3. 多点触控防护

    targetView.setOnTouchListener((v, event) -> {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            animatorSet.cancel(); // 中断未完成的动画
        }
        return false; // 保持点击事件穿透
    });

完整代码示例

// 获取视图
final View movingView = findViewById(R.id.moving_view);
// 初始化点击监听
movingView.setOnClickListener(v -> {
    // 获取当前坐标
    float currentX = movingView.getX();
    float currentY = movingView.getY();
    // 计算目标坐标(示例:对角线移动)
    float targetX = currentX + 300;
    float targetY = currentY + 200;
    // 创建动画集合
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.playTogether(
        ObjectAnimator.ofFloat(movingView, "x", currentX, targetX),
        ObjectAnimator.ofFloat(movingView, "y", currentY, targetY)
    );
    // 配置动画参数
    animatorSet.setDuration(600);
    animatorSet.setInterpolator(new OvershootInterpolator()); // 弹性效果
    animatorSet.start();
});

常见问题解答

Q1:为什么使用View Animation实现移动后视图会跳回原位?
A:View Animation仅修改视图的绘制位置,不会实际改变layout属性,解决方案:

  1. 改用Property Animator直接修改x/y属性
  2. 或在动画结束时手动更新布局参数:
    animator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
            params.leftMargin = (int)view.getX();
            params.topMargin = (int)view.getY();
            view.setLayoutParams(params);
        }
    });

Q2:如何实现点击后视图平滑移动到手指触摸位置?
A:需要结合GestureDetector获取触摸坐标,动态计算位移向量:

@Override
public boolean onTouch(View v, MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        float targetX = event.getRawX() v.getWidth()/2;
        float targetY = event.getRawY() v.getHeight()/2;
        ObjectAnimator xAnim = ObjectAnimator.ofFloat(v, "x", v.getX(), targetX);
        ObjectAnimator yAnim = ObjectAnimator.ofFloat(v, "y", v.getY(), targetY);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(xAnim, yAnim);
        set.setDuration(400);
        set.start();
    }
    return true; // 消费事件
}
0