Android中ImageView移动至屏幕中心后旋转异常:呈现大圈旋转而非绕自身中心旋转的问题求助
我来帮你搞定这个旋转偏移的问题!你遇到的这个“大圈旋转”现象,本质是补间动画(RotateAnimation)和属性动画(你用来移动View的animate()方法)的工作机制差异导致的,下面给你分析原因和两种解决方案:
问题根源
你用image.animate().x(...)这种方式是属性动画,它只是改变了View的绘制位置(视觉上的位置),但并没有更新View的真实布局参数(比如left/top这些布局坐标)。而RotateAnimation是补间动画,它计算旋转中心点时,是基于View的原始布局位置(也就是一开始在屏幕底部的位置),而不是你移动后的显示位置。所以当你设置Animation.RELATIVE_TO_SELF, 0.5f时,它找的是View原来在底部时的中心,自然就会绕着一个偏移的点转大圈了。
方案一:用属性动画做旋转(推荐,简洁统一)
既然移动用的是属性动画,旋转也统一用属性动画来实现,这样两者的坐标体系完全一致,直接基于View当前的显示位置计算中心点,不会有偏移问题。
替换你的旋转代码为:
// 直接用ViewPropertyAnimator实现旋转,默认就是绕自身中心旋转 image.animate() .rotation(360) // 旋转360度 .setDuration(duration) .setInterpolator(new DecelerateInterpolator(1.5f)) .start();
如果需要重复旋转,可以添加.setRepeatCount(ValueAnimator.INFINITE)来实现无限循环。
方案二:更新布局参数后再用补间动画
如果你一定要使用RotateAnimation,那需要在移动动画结束后,把ImageView的真实布局位置更新为移动后的坐标,这样补间动画就能正确识别View的当前中心了。
修改你的移动代码,添加动画监听器来更新布局:
image.animate() .y(metrics.heightPixels / 2 - image.getHeight() / 2) .x(metrics.widthPixels / 2 - image.getWidth() / 2) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { // 动画结束后,更新View的布局参数,将真实位置改为移动后的位置 ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) image.getLayoutParams(); params.leftMargin = (int) image.getX(); params.topMargin = (int) image.getY(); // 清除RelativeLayout中原有的alignParentBottom属性,避免布局冲突 if (params instanceof RelativeLayout.LayoutParams) { ((RelativeLayout.LayoutParams) params).addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0); } image.setLayoutParams(params); // 现在启动旋转动画,就会绕自身中心旋转了 RotateAnimation animRotate = new RotateAnimation(0.0f, 360.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animRotate.setDuration(duration); animRotate.setInterpolator(new DecelerateInterpolator(1.5f)); image.startAnimation(animRotate); } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }) .start();
另外补充一个小细节:你给ImageView设置了layout_width="match_parent",这会让它的宽度和屏幕一致,不过这不会影响旋转中心点的问题,只是如果你的图片本身不是全屏的,scaleType="centerCrop"会裁剪图片,视觉上的中心还是和View的中心一致的。
内容的提问来源于stack exchange,提问作者rcr

