Android 仿卡片消消除

    最近产品看到一个儿童趣味匹配游戏,叫**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.csdn.net/download/greatdaocaoren/12752108

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值