图片缩小到指定位置动画的踩坑记录

    最近遇到个小问题,需要做一个全屏图片缩小到指定大小view上面的动画,有点像相册里面大图照片恢复到小图的那种感觉,本来以为没啥难度的,结果还是遇到了些坑,记录一下以免后面忘记了。

    整体的思路是比较简单的,开始界面上展示的是大图,长和宽分别按照相应的比例收缩,(大图和最后的小图不一定是一个长宽比,需要分别算收缩比例),收缩比例按照相应的View的getWidth()和getHeight()来相除,最后设置一下动画的时间等参数就应该能做到了。

    踩坑一:相应的view使用getWidth()和getHeight()没有正确的获取长宽值,结果都是0。这个问题比较好解决,看到结果是0,第一反应就是相关方法调用的时机不对,相应的getWidth()和getHeight()还没有被设值,得到的就是0 了,相关的参数在activity生命周期里的排序这里省略一下,网上比较多的资料,对我们干活的来说,只要明白在onWindowFocusChanged方法或之后的方法里面进行相应的取长宽值操作是OK的就好了。下面就是分别获取长宽收缩比例的句子,都转为float是为了方便后面的计算。可以在onWindowFocusChanged方法里面先加一个状态值,来确保这个动画只会执行一次。

float child_width = (float) img_small.getWidth();
float child_height = (float) img_small.getHeight();
float parent_width = (float) img_big.getWidth();
float parent_height = (float) img_big.getHeight();
float scaleX = child_width / parent_width;
float scaleY = child_height / parent_height;

    踩坑二:动画设置完后,发现缩小后的图和指定位置有些许偏差,一般体现在高度上,宽度上比例一般都没啥问题,个人感觉可能是导航栏或者状态栏的高度造成的干扰,而状态栏的高度还和机型啊,横竖啊等有关,具体的高度值还需要看项目的情况,这里说一下我搜到的一种查询导航栏高度的方法,navigation_bar_height_landscape和navigation_bar_height是横竖时候的导航栏宽度,一般来说是一样的。(处理了导航栏高度以后还是有一丢丢的偏差,没想出来是为啥导致的,暂时先放放)

Resources resources = getResources();
int resourceId = resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android");
//int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
int height = resources.getDimensionPixelSize(resourceId);

    踩坑三:动画设置缩放的中心点问题,由于前面也说了, 缩放后的图不见得是原图的长宽比,也不见得是正中心的,需要确认一个正确的中心点才行,这里我使用的是ScaleAnimation的缩放动画,两个1是初始的长宽比例,后面的scaleX*0.9是缩放后的横轴比例,乘以了0.9是为了避免有些许偏差或者小图圆角导致缩小后的大图不能完全被小图遮盖住,Animation.RELATIVE_TO_SELF是针对后面参数的,这个值是说针对自己的比例来缩小,后面的参数就是一个比例系数,比如缩小到左边1/4处,后面的参数就是0.25f,Animation.ABSOLUTE是绝对值,后面的参数就是像素值,比如中心点事左边100像素,后面参数就填100,还有一个Animation.RELATIVE_TO_PARENT,是针对这个view的父组件来说的,后面也是跟一个比例系数,(img_small.getLeft() + child_width / 2f) / parent_width是计算缩放中心的横向坐标的,getLeft()可以获得view离父组件左边的距离,(这里横向的缩小没啥问题,纵向的有点偏差,尚不知道为啥造成的)。setFillAfter(true)代表缩小后保持缩小状态不还原,setRepeatCount(0)代表动画只出现一次,setDuration(500)代表动画持续时间是500毫秒。最后就是startAnimation了。

ScaleAnimation animation = new ScaleAnimation(1, scaleX * 0.9f, 1 , scaleY * 0.9f,
                Animation.RELATIVE_TO_SELF, (img_small.getLeft() + child_width / 2f) / parent_width,
                Animation.RELATIVE_TO_SELF, (img_small.getTop() + child_height / 2f) / (parent_height - height));
animation.setFillAfter(true);
animation.setRepeatCount(0);
animation.setDuration(500);
img_big.startAnimation(animation);

    踩坑四:XML中的margin和padding对计算的影响,XML中如果相应的view设置了margin和padding之类的,会对代码中的中心值计算产生干扰,需要把相应的margin值考虑进去,下面是代码中获取marginbottom值的方法,计算中心点的时候需要考虑进去。或者和我一样偷点懒,不用margin之类的属性,用空白的view来相应的挤占位置达到margin的效果也是可以的

ViewGroup.LayoutParams params = img_small.getLayoutParams();
ViewGroup.MarginLayoutParams marginParams = null;
//获取view的margin设置参数
if (params instanceof ViewGroup.MarginLayoutParams) {
marginParams = (ViewGroup.MarginLayoutParams) params;
} else {
//不存在时创建一个新的参数
marginParams = new ViewGroup.MarginLayoutParams(params);
}
int bottom_margin = marginParams.bottomMargin

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值