最近产品看到一个儿童趣味匹配游戏,叫**match,然后就叫客户端直接实现,然后新增到APP里的一个小模块里,看到这个也挺有意思的,就记录下来,下面先看看效果图吧:
效果看着挺简单,主要难点有两个,第一个动画处理,设计到旋转,缩放,透明度的处理;第二个难点就是这个item是放在recyclerview中的,因此这个数量是不固定的,可以自己增加,也可以改变gridview的摆放样子。
首先来看看动画方面吧,首先将一个卡片分为背面和正面两部分,点击卡片时候,卡片的旋转也是正面和背面的旋转,比如一个是从0到180度的旋转,那另外一个就是负的180度到0度的旋转,这样就能给人感觉是一体的,然后就是一个透明度的同时进行,一个是从不透明到透明的转变,另外一个是从透明到不透明的变化,如果正面和背面一起执行这样的变化,那么就整保证无缝连接的卡片旋转了。那么就来看看这个animator的xml是如何实现的吧:
card_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--在开始时是隐藏, 逆向旋转, 当旋转一半时, 显示卡片-->
<!--完全透明-->
<objectAnimator
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0"
android:duration="0"
/>
<!--旋转-->
<objectAnimator
android:propertyName="rotationY"
android:valueFrom="-180"
android:valueTo="0"
android:duration="1000"
/>
<!--显示出来-->
<objectAnimator
android:propertyName="alpha"
android:valueFrom="0.0"
android:valueTo="1.0"
android:duration="0"
android:startOffset="500"
/>
</set>
card_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--旋转180°, 当旋转一半时, 卡片消失.-->
<!--旋转180-->
<objectAnimator
android:propertyName="rotationY"
android:valueFrom="0"
android:valueTo="180"
android:duration="1000"
/>
<!--变成透明-->
<objectAnimator
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0"
android:startOffset="500"
android:duration="0"
/>
</set>
然后就是逻辑处理,遇到不相同卡片时候就将这个动画反着再执行一次,就能恢复到最开始点击之前的样子了。如果点击到相同的卡片,那么这时两卡片就要同时消失,这里需要一个消失的动画,及X轴和Y轴同时从1到0的缩放,透明度也是从1到0的缩放,这样就能让其消失了:
card_disappear.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="0"
android:duration="1000"
/>
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="1.0"
android:valueTo="0"
android:duration="1000"
/>
<!--变成透明-->
<objectAnimator
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0"
android:startOffset="1000"
android:duration="0"
/>
</set>
第二个麻烦点就是给适配器增加一个接口回调,给卡片一个点击事件,但是这个点击事件要控制住两点,第一,正在执行动画的时候是不能点击的,要不然动画就会紊乱,第二,两个相同卡片消失之后也是不能继续点击的,这么就需要给卡片实体赋值一个变量,消失之后就改变这个变量,当再次点击就直接return掉就行了。对于第一个正在执行的动画,得在监听动画执行完毕之后,再通过适配器公共出来的api去改变这个flag标记,让其可以继续点击。下面就是适配器里的代码:
package com.leo.matchdemo;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.bumptech.glide.Glide;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.List;
public class MatchAdapter extends BaseQuickAdapter<MatchBean, BaseViewHolder> {
public MatchAdapter(List<MatchBean> data) {
super(R.layout.item_match, data);
}
private boolean isCanClick = true;
public void setClickAble(boolean isCanClick) {
this.isCanClick = isCanClick;
}
@Override
protected void convert(final BaseViewHolder helper, final MatchBean result) {
if (result == null) {
return;
}
final RelativeLayout rl_content = helper.getView(R.id.rl_content);
final ImageView im_back = helper.getView(R.id.im_back);
final ImageView im_front = helper.getView(R.id.im_front);
Glide.with(getContext()).asBitmap().load(result.getImgUrl()).into(im_back);
if (result.isShowing()) {
im_back.setVisibility(View.VISIBLE);
im_front.setVisibility(View.VISIBLE);
} else {
im_back.setVisibility(View.GONE);
im_front.setVisibility(View.GONE);
}
rl_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isCanClick && result.isShowing()) {
if (null != itemClickAction) {
if (!result.isFrontFlag()) {
itemClickAction.frontClick(result.getTargetId(), rl_content, im_back, im_front);
result.setFrontFlag(!result.isFrontFlag());
}
}
}
}
});
}
private ItemClickAction itemClickAction;
public void setItemClickAction(ItemClickAction itemClickAction) {
this.itemClickAction = itemClickAction;
}
public interface ItemClickAction {
void frontClick(String matchingId, RelativeLayout contentView, ImageView backImg, ImageView frontImg);
}
}
但很重要很重要的一点就是在卡片相同匹配之后,不要notify适配器,这样就又会恢复原状了,这就达不到这个效果了。因此就直接将接口回调给页面里的view进行显示与消失的操作就行了。
如果需要demo下载,这里也附上下载链接:
https://download.youkuaiyun.com/download/greatdaocaoren/12752108