仿蚂蚁森林能量球效果遇到的问题记录
常规先上图
前提内容
仿做一个蚂蚁森林的能量球效果,计划使用属性动画,来实现能量球上下摆动,然后点击能量球有一个收集的动画。
本来以为就这么几个简单的需求不会太难,做完后发现问题:
问题:
页面动画太多会卡顿,出现动画不流畅的问题,并且内存占用率很高。
在使用动画的时候要特别注意动画的回收工作,否则内存会出现占用过高的问题。
给每个view设置动画显然不是很好,数量少可能不明显,如果数量很多就会卡的不动了了。
思路:
将所有的能量球添加统一的一个动画,然后每个能量球的移动距离和速度不同,通过消息去更新所有的能量球位置。
过程:
1.初始化指定数量的能量球(view),并设置一些需要的属性。
private void drawMyCircle() {
for (int i = 0; i < waterList.size(); i++) {
View view = mInflater.inflate(R.layout.item_grid_view, this, false);
TextView textView = view.findViewById(R.id.tv_grid);
textView.setText(waterList.get(i).value + "g");
textView.setTag(R.string.value, waterList.get(i));
textView.setTag(R.string.speed, speList[mRandom.nextInt(speList.length)]);
textView.setTag(R.string.isUP, mRandom.nextBoolean());
//设置view位置
setViewLocation(textView);
//将初始化好的view添加到容器
addView(textView);
//设置点击事件
textView.setOnClickListener(this);
waterViewList.add(textView);
}
//开始移动容器中所有的能量球了
mHandler.sendEmptyMessage(1);
}
这里需要的属性有几种,1.能量球的显示样式,包括大小、颜色、透明度 2.能量球具体在容器中的位置,这也是一个比较重要的点,这里我只是通过随机数来处理的,可以通过算法来尽量保证球的不重合。3.能量球的点击事件。4.保存所有的能量球view
2.能量球放到容器view中,并开始播放动画。
private void setViewOffset() {
for (int i = 0; i < waterViewList.size(); i++) {
TextView textView = waterViewList.get(i);
float y = textView.getY();
//偏移方向
Boolean isUP = (Boolean) textView.getTag(R.string.isUP);
//速度
float speed = (float) textView.getTag(R.string.speed);
//原始坐标
float originalY = (float) textView.getTag(R.string.originalY);
//移动的坐标
float translationY;
if (isUP) {
translationY = y - speed;
} else {
translationY = y + speed;
}
if (translationY - originalY > VIEW_OFFSET) {
translationY = originalY + VIEW_OFFSET;
textView.setTag(R.string.isUP, true);
} else if (translationY - originalY < -VIEW_OFFSET) {
translationY = originalY - VIEW_OFFSET;
textView.setTag(R.string.isUP, false);
setSpe(textView);
}
textView.setY(translationY);
}
}
播放动画需要注意的问题:
首先我们不能使用动画来做,虽然动画写起来比较简单,因为在页面上同时播放过多的动画会导致页面卡顿,内存暴涨(我用动画的方式写了,大约10个球就有点卡了)。
这里选择的是循环去改变每个view的球的y轴上的位置来模拟动画,并且通过handler来循环改变球的位置,消息发送的间隔控制在20毫秒内。测试放过200个球,动画比较平滑。
3.点击能量球后要移除并伴随一个动画。
/**
* 移除动画
*
* @param view
*/
private void removeViewAnimation(final View view) {
//清除抖动动画
view.clearAnimation();
Interpolator Interpolator = new LinearInterpolator();
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(view, "translationY", viewHeight - textWidth);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(view, "translationX", textWidth);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 0.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 0.0f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.0f);
AnimatorSet set = new AnimatorSet();
set.setInterpolator(Interpolator);
set.playTogether(transYAnim, transXAnim, scaleXAnim, scaleYAnim, alphaAnim);
//不同距离可以设置不同的时间,需要通过移动的距离来计算时间,不过我
// int maxLine = viewHeight * viewHeight + viewWidth * viewWidth;
// int towPointDistance = getTowPointDistance(new Point((int)view.getX(), (int)view.getY()),new Point(0,viewHeight));
// int time = (int) (Math.sqrt(maxLine) / towPointDistance * 1000);
// set.setDuration(1000);
set.setDuration(1000);
set.start();
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.clearAnimation();
removeView(view);
}
});
}
这里就是简单的使用的属性动画,动画很少写,就算是熟悉了一下。
finish
简单做个记录,不断学习,欢迎指教。