Android Studio使用Java实现翻牌动画的图像替换时序问题求解
Android 翻牌记忆游戏实现方案
问题原因
你当前的代码会先替换图片再执行动画,是因为ViewPropertyAnimator的动画是异步执行的,调用rotationYBy()后不会阻塞后续代码,setImageResource()会立刻执行。
基础翻牌逻辑修复
要实现旋转到90度(卡片侧面朝向用户,不可见内容)时再替换图片,再完成剩余90度旋转,需要给动画添加执行监听,修复后的代码如下:
// 提前给每个ImageView设置初始的背面图片,比如R.drawable.card_back public void flipCard(View view) { ImageView card = (ImageView) view; // 避免重复点击已翻开的卡片 if ((boolean) card.getTag(R.id.is_flipped)) { return; } // 先转90度,此时卡片完全不可见 card.animate().rotationYBy(90f).setDuration(150).withEndAction(() -> { // 替换为正面图片,可根据卡片对应的实际图案动态设置 card.setImageResource(R.drawable.ex1); // 标记为已翻开 card.setTag(R.id.is_flipped, true); // 继续转剩下的90度,展示正面 card.animate().rotationYBy(90f).setDuration(150).start(); }).start(); }
注意:需要提前在res/values/ids.xml中添加自定义id
<item type="id" name="is_flipped" />,用来存储卡片的翻开状态,也可以用全局HashMap来存储状态。
匹配判断、自动翻回、计分功能实现
你需要先在Activity中添加如下全局变量:
private ImageView firstFlippedCard = null; // 第一张翻开的卡片 private int score = 0; // 当前得分 private boolean isProcessing = false; // 防止同时翻多张卡片导致逻辑混乱
完整的翻牌逻辑如下:
public void flipCard(View view) { ImageView card = (ImageView) view; // 正在处理匹配逻辑、卡片已翻开时直接拦截点击 if (isProcessing || (boolean) card.getTag(R.id.is_flipped)) { return; } isProcessing = true; // 执行翻转动画,翻到正面 card.animate().rotationYBy(90f).setDuration(150).withEndAction(() -> { // 获取当前卡片对应的图案id,需要提前给每个卡片设置tag存储对应的图案值 int cardPattern = (int) card.getTag(R.id.card_pattern); card.setImageResource(cardPattern); card.setTag(R.id.is_flipped, true); card.animate().rotationYBy(90f).setDuration(150).withEndAction(() -> { isProcessing = false; // 判断是第一张还是第二张翻开的卡片 if (firstFlippedCard == null) { firstFlippedCard = card; } else { // 两张都翻开了,判断是否匹配 int firstPattern = (int) firstFlippedCard.getTag(R.id.card_pattern); int secondPattern = (int) card.getTag(R.id.card_pattern); if (firstPattern == secondPattern) { // 匹配成功,得分+1 score++; // 此处自行更新计分UI firstFlippedCard = null; } else { // 匹配失败,延迟1秒后两张都翻回背面 isProcessing = true; card.postDelayed(() -> { // 翻回第二张 flipBack(card); // 翻回第一张 flipBack(firstFlippedCard); firstFlippedCard = null; isProcessing = false; }, 1000); } } }).start(); }).start(); } // 翻回背面的复用方法 private void flipBack(ImageView card) { card.animate().rotationYBy(90f).setDuration(150).withEndAction(() -> { card.setImageResource(R.drawable.card_back); card.setTag(R.id.is_flipped, false); card.animate().rotationYBy(90f).setDuration(150).start(); }).start(); }
注意事项
- 需要提前给每个卡片的ImageView设置两个tag:一个存储当前卡片对应的图案资源id(
R.id.card_pattern同样需要在ids.xml中定义),另一个存储是否已经翻开的状态 - 动画时长可以根据需求自行调整
内容的提问来源于stack exchange,提问作者Slavbabushka69
相关产品推荐
相关产品推荐

