Android中如何通过动画实现苹果落入篮子并展示篮内苹果?
实现苹果落入篮子的动画与填充效果
嘿,我来帮你搞定这个苹果落篮子的动画和填充效果!你现有的拖拽逻辑已经搭好基础了,咱们只需要在拖拽完成的节点加上动画,再优化篮子里的苹果展示逻辑就行。
一、先调整布局:给篮子加个容器
首先,把你的篮子ImageView放到一个FrameLayout里,这样我们可以在篮子上面叠加多个苹果视图,模拟填充效果:
<FrameLayout android:id="@+id/basket_container" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/basket_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/basket" /> </FrameLayout>
二、添加苹果落入的动画
当用户把苹果拖到篮子上松开(ACTION_DROP事件),我们需要给苹果加一个下落+弹跳的动画,模拟真实落入篮子的物理效果。可以用AnimatorSet组合平移、缩放和透明度动画:
private void animateAppleIntoBasket(View appleView, View basketView) { // 获取篮子在屏幕上的坐标 int[] basketPos = new int[2]; basketView.getLocationOnScreen(basketPos); int basketCenterX = basketPos[0] + basketView.getWidth() / 2; int basketBottomY = basketPos[1] + basketView.getHeight(); // 获取拖拽苹果当前的坐标 int[] applePos = new int[2]; appleView.getLocationOnScreen(applePos); // 计算苹果需要移动的距离:从当前位置到篮子底部中心 float moveX = basketCenterX - (applePos[0] + appleView.getWidth() / 2); float moveY = basketBottomY - applePos[1]; // 创建动画集合 AnimatorSet animSet = new AnimatorSet(); // 平移动画 ObjectAnimator animX = ObjectAnimator.ofFloat(appleView, "translationX", 0, moveX); ObjectAnimator animY = ObjectAnimator.ofFloat(appleView, "translationY", 0, moveY); // 给Y轴平移加弹跳插值器,模拟下落砸到篮子的回弹效果 animY.setInterpolator(new BounceInterpolator()); // 缩放动画:模拟落入时的轻微挤压 ObjectAnimator scaleX = ObjectAnimator.ofFloat(appleView, "scaleX", 1f, 0.8f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(appleView, "scaleY", 1f, 0.8f, 1f); // 透明度动画:动画结束后隐藏原拖拽苹果 ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(appleView, "alpha", 1f, 0f); // 设置动画时长,这里用800毫秒,你可以根据需求调整 animSet.setDuration(800); // 先执行平移+缩放,延迟200毫秒后执行透明度动画 animSet.playTogether(animX, animY, scaleX, scaleY); animSet.play(alphaAnim).after(600); // 动画结束后的处理:隐藏原拖拽视图 animSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { appleView.setVisibility(View.GONE); } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }); animSet.start(); }
三、动态填充篮子里的苹果
我们可以在篮子的FrameLayout容器里动态添加小尺寸的苹果视图,让它们错落有致地分布在篮子里,看起来更真实:
private void addAppleToBasket(ViewGroup basketContainer) { // 创建一个新的苹果视图 ImageView basketApple = new ImageView(this); basketApple.setImageResource(R.drawable.apple); // 设置篮子里苹果的尺寸(比拖拽的苹果小一点) int appleSize = getResources().getDimensionPixelSize(R.dimen.apple_in_basket_size); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(appleSize, appleSize); basketApple.setLayoutParams(params); // 随机生成偏移量,让苹果在篮子里分布更自然 Random random = new Random(); int maxXOffset = basketContainer.getWidth() / 2 - appleSize / 2; int maxYOffset = basketContainer.getHeight() / 2 - appleSize / 2; // X轴左右偏移 int xOffset = random.nextInt(maxXOffset * 2) - maxXOffset; // Y轴只向上偏移,避免超出篮子底部 int yOffset = random.nextInt(maxYOffset) - maxYOffset; basketApple.setTranslationX(xOffset); basketApple.setTranslationY(yOffset); // 添加到篮子容器中 basketContainer.addView(basketApple); }
四、修改你的拖拽代码,整合逻辑
现在把上面的动画和填充逻辑整合到你现有的onDrag方法的ACTION_DROP分支里:
@Override public boolean onDrag(View v, DragEvent event) { final int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: v.invalidate(); return true; case DragEvent.ACTION_DRAG_ENTERED: v.invalidate(); return true; case DragEvent.ACTION_DRAG_LOCATION: return true; case DragEvent.ACTION_DRAG_EXITED: v.invalidate(); return true; case DragEvent.ACTION_DROP: v.invalidate(); if (v instanceof ImageView) { ImageView basketView = (ImageView) v; // 获取篮子的容器FrameLayout ViewGroup basketContainer = (ViewGroup) basketView.getParent(); // 1. 执行苹果落入动画 animateAppleIntoBasket(dragImageView, basketView); // 2. 往篮子里添加一个苹果视图 addAppleToBasket(basketContainer); // 3. 更新计数并隐藏原拖拽视图 dragImageView.setImageBitmap(null); successCount++; } else { CommonMethods.showSweetAlertDialog(SPLevelOneMoveObjectTBActivity.this, false); } return true; case DragEvent.ACTION_DRAG_ENDED: v.invalidate(); Log.v("ACTION_DRAG_ENDED", "ACTION_DRAG_ENDED"); if (!isSuccess && !isFail) { isFail = true; CommonMethods.showSweetAlertDialog(SPLevelOneMoveObjectTBActivity.this, false); return true; } return true; default: break; } return false; }
一些额外的优化建议
- 如果你的拖拽苹果是复用的视图,建议创建一个新的ImageView来执行动画,避免原视图被动画影响
- 可以给篮子设置容量上限,当
successCount达到上限时,提示用户任务完成 - 动画的时长、插值器参数可以根据你的UI风格调整,比如自定义弹跳插值器来控制回弹幅度
内容的提问来源于stack exchange,提问作者Armita Kumari
相关产品推荐
相关产品推荐

