仿直播间玩色子游戏,AnimatorSet的综合使用

转载请标明出处:
http://blog.csdn.net/Iamzgx/article/details/53168567
本文出自:【iGoach的博客】

最近一直在做直播的功能,所以平时也抽时间总结下这些功能,今天就来说下直播间玩色子游戏,这个功能在抱抱app里面就有。感兴趣的同学可以去看下。

其实这功能也不算太难,只能说他是AnimatorSet的结合体,把步骤分清楚就好写了,连TypeEvaluator接口都不用实现。

注意:这里说的是使用AnimatorSet,不是AnimationSet。他两有什么区别呢?AnimatorSet用于Property Animation,AnimationSet用于View Animation。现在google提倡使用Property Animation。而且很早就提供了nineoldandroids向下兼容包,这里我们也用这个兼容包.

这个动画仔细看下,我们会发现,它的动画范围是在整个屏幕,那么我们可以先准备好我们要做动画的View,然后把这些动画通过AnimatorSet串联起来start就行了。下面就来创建这些View吧。
首先是带色子的托盘,我们可以通过自定义LinearLayout创建,这个ViewGroup可以通过设置的点数显示不同的色子点数。把它命名为DiceLayout。先定义它的几个属性

 <declare-styleable name="DiceLayout">
        <attr name="drawableName" format="string"/>
        <attr name="isTray" format="boolean"/>
    </declare-styleable>

这里解释下上面的几个属性,drawableName主要是通过getIdentifier找资源的时候要用到的资源名。isTray主要控制色子是否是水平排列。

属性定义好之后,接下来就是查找属性然后添加色子view,具体看下面代码

public DiceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DiceLayout);
        drawableName = typedArray.getString(R.styleable.DiceLayout_drawableName);
        isTray = typedArray.getBoolean(R.styleable.DiceLayout_isTray,true);
        if(TextUtils.isEmpty(drawableName))
            drawableName = DEFAULT_DRAWABLE_NAME;
        typedArray.recycle();
        setGravity(Gravity.CENTER);
        setOrientation(LinearLayout.HORIZONTAL);
        Random random = new Random();
        setDiceNum(new int[]{1+random.nextInt(6),1+random.nextInt(6),1+random.nextInt(6)});
    }

    public void setTray(boolean tray) {
        isTray = tray;
    }

    public void setDrawableName(String drawableName) {
        if(!TextUtils.isEmpty(drawableName))
        this.drawableName = drawableName;
    }
    private ImageView addDiceView(int position){
        ImageView imageView = new ImageView(getContext());
        LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
       if(isTray){
           if(position!=0)
               layoutParams.leftMargin = DensityUtil.dip2px(getContext(),5);
           if(position!=1)
               layoutParams.bottomMargin = DensityUtil.dip2px(getContext(),5);
       }
        imageView.setLayoutParams(layoutParams);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        return imageView;
    }

上面主要是查找属性进行初始化,然后设置一个默认的初始化点数。同时添加了set属性方法。
然后实现对外设置色子数方法

    public void setDiceNum(int[] rockNumberResults){
        if(rockNumberResults.length!=3)
            rockNumberResults = new int[]{1,1,1};
        int firstDiceNum = cling(1,6,rockNumberResults[0]);
        int secondDiceNum = cling(1,6,rockNumberResults[1]);
        int threeDiceNum = cling(1,6,rockNumberResults[2]);
        removeAllViews();
        int firstDiceRes = getContext().getResources().getIdentifier(drawableName+firstDiceNum,
                "drawable",getContext().getPackageName());
        int secondDiceRes = getContext().getResources().getIdentifier(drawableName+secondDiceNum,
                "drawable",getContext().getPackageName());
        int threeDiceRes = getContext().getResources().getIdentifier(drawableName+threeDiceNum,
                "drawable",getContext().getPackageName());
        for (int i = 0; i < 3; i++) {
            ImageView childView = addDiceView(i);
            childView.setImageResource(i==1?secondDiceRes:i==2?threeDiceRes:firstDiceRes);
            addView(childView);
        }
    }
    public void startRotationAnim(int[] DiceNumberResults){
        startRotationAnim(DiceNumberResults,-1);
    }
    public void startRotationAnim(final int[] DiceNumberResults,final int animTime){
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            if(childView instanceof ImageView){
                ImageView diceIv = (ImageView)childView;
                diceIv.setImageResource(R.drawable.dice_user_anim);
                final AnimationDrawable animDrawable = (AnimationDrawable) diceIv.getDrawable();
                if(animTime>=0){
                    Observable.timer(animTime, TimeUnit.SECONDS)
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Action1<Long>() {
                                @Override
                                public void call(Long aLong) {
                                    animDrawable.stop();
                                    setDiceNum(DiceNumberResults);
                                }
                            });
                }
                animDrawable.start();
            }
        }
    }
    public static int cling(int min, int max, int value) {
        return Math.min(Math.max(min, value), max);
    }

解释下上面代码,这里把色子数传递,然后重置色子这三个子view,通过getIdentifier查找资源id设置色子对应点数的图片。其中getIdentifier的使用为

通过getResource获取getIdentifier方法,getIdentifier方法三个参数分别为资源名,资源所在的路径名,资源所在的包名

同时提供一个开始旋转色子数的动画方法startRotationAnim,这里我尝试使用了propertyAnimation来做旋转效果,效果不太好,所以这里我使用Drawable Animation来实现效果更好。由于Drawable Animation只能配置android:oneshot为true or false来执行一遍或者无限循环,所以这里我使用定时器来实现旋转传递的时间animTime后停止动画,定时器使用rxJava实现。

注意Rx需要在build引入包,配置好即可使用,无需jar包

  compile 'io.reactivex:rxandroid:1.1.0'
  compile 'io.reactivex:rxjava:1.1.0'

同时提供下简单的drawable animation 的xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/dice_d_1"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_2"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_3"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_4"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_5"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_6"
        android:duration="10"/>
    <item
        android:drawable="@drawable/dice_d_7"
        android:duration="10"/>
</animation-list>

托盘创建好之后,接下来通过自定义RelativeLayout,在自定义RelativeLayout里面添加托盘和色盅,以及处理动画。这里命名为DiceAnimLayout

在DiceAnimLayout里面先addView

private void addChildView(){
        //添加托盘
        trayLayout = new DiceLayout(getContext());
        trayLayout.setDrawableName("dice_icon");
        trayLayout.setTray(true);
        trayLayout.setBackgroundResource(R.drawable.dice_tray_icon);
        LayoutParams diceLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        diceLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,RelativeLayout.TRUE);
        diceLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        diceLayoutParams.bottomMargin = DensityUtil.dip2px(getContext(),110);
        trayLayout.setLayoutParams(diceLayoutParams);
        addView(trayLayout);
        //添加盖子
        diceCap = new ImageView(getContext());
        LayoutParams diceCapParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        diceCapParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        diceCapParams.topMargin = -DensityUtil.dip2px(getContext(),197);
        diceCap.setLayoutParams(diceCapParams);
        diceCap.setScaleType(ImageView.ScaleType.CENTER_CROP);
        diceCap.setImageResource(R.drawable.dice_cap_icon);
        addView(diceCap);
        //添加盖住view
        mDiceCapedRl = LayoutInflater.from(getContext()).inflate(R.layout.dice_cap_layout,this,false);
        addView(mDiceCapedRl);
        trayLayout.setVisibility(View.INVISIBLE);
        diceCap.setVisibility(View.INVISIBLE);
        mDiceCapedRl.setVisibility(View.INVISIBLE);
    }

上面添加了托盘和色盅,还有就是合起来之后的ViewGroup,这里通过布局来提供,当然可以直接切图,但是这里为了减少图片资源,所以这样处理
dice_cap_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="110dp"
    android:layout_height="217dp">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:layout_alignParentBottom="true"
        android:src="@drawable/dice_tray_icon"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:src="@drawable/dice_cap_icon"/>
</RelativeLayout>

添加好view之后,我们就要来分析下这个动画步骤了。

  1. 色盅掉下来移动到托盘地方
  2. 色盅和托盘合起来之后向下缓冲移动一点距离
  3. 然后向上移动一段距离,
  4. 再左右旋转30度,循环执行动画几次
  5. 然后下移到托盘位置,
  6. 色盅上移打开
  7. 托盘显示色子,显示2s后消失

具体看下代码

 private DiceLayout trayLayout;
 private ImageView diceCap;
 private View mDiceCapedRl;
 private AnimatorSet allAnimSet;
 //托盘合起来的高度
 private final int DICE_CAPED_HEIGHT = DensityUtil.dip2px(getContext(),17) ;
 //合起来后向上移动的位置
 private final int UP_AND_DOWN_Y = DensityUtil.dip2px(getContext(),193) ;
 //合起来后向下缓冲位移
 private final int MOVE_BUFFER_Y = DensityUtil.dip2px(getContext(),10) ;
 private final int ANIM_DURING_TIME = 500 ;
 private AnimEndListener animEndListener;

public void startAnimation(final int[] rockNumberResults){
        if(allAnimSet.isStarted())
            return;
        diceCap.setVisibility(View.VISIBLE);
        trayLayout.setVisibility(View.VISIBLE);
        trayLayout.setAlpha(1.0f);
        mDiceCapedRl.setVisibility(View.INVISIBLE);
        //托盘高度为DICE_CAPED_HEIGHT
        ValueAnimator capTransAnim = ObjectAnimator.ofFloat(diceCap,"translationY",0,trayLayout.getBottom()- DICE_CAPED_HEIGHT);
        capTransAnim.setDuration(ANIM_DURING_TIME);
        capTransAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mDiceCapedRl.setVisibility(View.VISIBLE);
                diceCap.setVisibility(View.INVISIBLE);
                trayLayout.setVisibility(View.INVISIBLE);
                animation.removeAllListeners();
            }
        });
        //合起来之后向下缓冲运动
        ValueAnimator downDiceCapedTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",0,MOVE_BUFFER_Y);
        downDiceCapedTransAnim.setInterpolator(new DecelerateInterpolator());
        downDiceCapedTransAnim.setDuration(20);
        //合起来之后向上移动
        ValueAnimator upTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",MOVE_BUFFER_Y,-UP_AND_DOWN_Y);
        upTransAnim.setDuration(ANIM_DURING_TIME);
        //旋转
        ValueAnimator rotationAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"rotation",30.0f,-30.0f,0.0f);
        mDiceCapedRl.setPivotX(mDiceCapedRl.getWidth()/2);
        mDiceCapedRl.setPivotY(0);
        rotationAnim.setRepeatCount(5);
        rotationAnim.setDuration(ANIM_DURING_TIME);
        //向下移动
        ValueAnimator downTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",-UP_AND_DOWN_Y,0);
        upTransAnim.setDuration(ANIM_DURING_TIME);
        //盖子向上移动消失
        ValueAnimator capUpAnim = ObjectAnimator.ofFloat(diceCap,"translationY",mDiceCapedRl.getBottom()- DICE_CAPED_HEIGHT,0);
        capUpAnim.setDuration(ANIM_DURING_TIME);
        capUpAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                mDiceCapedRl.setVisibility(View.INVISIBLE);
                setDiceTrayNum(rockNumberResults);
                diceCap.setVisibility(View.VISIBLE);
                trayLayout.setVisibility(View.VISIBLE);
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                diceCap.setVisibility(View.INVISIBLE);
                if(animEndListener!=null)
                    animEndListener.AnimEnd();
                animation.removeAllListeners();
            }
        });
        //托盘显示2s后消失
        ValueAnimator trayAlphaAnim = ObjectAnimator.ofFloat(trayLayout,"alpha",1.0f,0.0f);
        trayAlphaAnim.setDuration(50);
        trayAlphaAnim.setStartDelay(2000);
        allAnimSet.playSequentially(capTransAnim,downDiceCapedTransAnim,upTransAnim,rotationAnim,
                downTransAnim,capUpAnim,trayAlphaAnim);
        allAnimSet.start();
    }
    public void setDiceTrayNum(int[] rockNumberResults){
        trayLayout.setDiceNum(rockNumberResults);
    }
    public void setAnimEndListener(AnimEndListener animEndListener){
        this.animEndListener = animEndListener;
    }
    public interface AnimEndListener{
        void AnimEnd();
    }

上面代码只要按照上面步骤看,就很简单了。在合起来的时候我们把托盘和色盅暂时INVISIBLE,合起来的View显示出来,然后对合起来的View进行动画操作,通过AnimatorSet来结合translationY移动动画,rotation旋转动画,这里旋转5个周期,以及alpha透明动画,具体位置可以getBottom()活着getTop()等方法获取。具体按标注给的效果图调整

注意

view.getBottom()或者view.getTop(),view.getWidth无法再onCreate等这些view还没绘制完前就调用的方法里面获取,所以我们要在veiw绘制完之后调用这些方法才有效果

最后来看下类似直播送礼的动效展示色子点数,实现和DiceAnimLayout类似,这里叫DiceUserAnimLayout。

首先我们定义一些view属性

private LayoutInflater mLayoutInflater;
    private View mFirstLineDiceView;
    private View mSecondLineDiceView;
    private View mThreeLineDiceView;
    private AnimatorSet mFirstAnimatorSet;
    private AnimatorSet mSecondAnimatorSet;
    private AnimatorSet mThreeAnimatorSet;
    private List<DicePo> mFirstAnimList;
    private List<DicePo> mSecondAnimList;
    private List<DicePo> mThreeAnimList;
    private boolean firstIsShow;
    private boolean secondIsShow;
    private boolean threeIsShow;

这里创建的是三行效果,所以需要三行view,分别对应一个AnimatorSet 和一个是否显示的标示

同样以布局实现效果,效果和布局如下

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/trans_round_shape"
    android:orientation="horizontal"
    >
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_marginRight="5dp"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="3dp"
        android:layout_weight="1">
        <TextView
            android:id="@+id/id_play_gift_name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/white"
            android:textSize="10sp"
            android:maxEms="8"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="昵称"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            />
        <com.common.animdemo.view.DiceLayout
            android:id="@+id/id_user_dice_dl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:drawableName="img_dmx_sz_"
            app:isTray="false"/>
    </LinearLayout>
    <ImageView
        android:id="@+id/id_dice_user_head_icon_iv"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_margin="2dp"
        android:scaleType="centerCrop"
        android:src="@drawable/head"/>
</LinearLayout>

把布局绑定在三个view上面,实现三行的效果。

public DiceUserAnimLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOrientation(LinearLayout.VERTICAL);
        mFirstAnimList = new ArrayList<>();
        mSecondAnimList = new ArrayList<>();
        mThreeAnimList = new ArrayList<>();
        mLayoutInflater = LayoutInflater.from(getContext());
        mFirstLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);
        mSecondLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);
        mThreeLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);
        LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        layoutParams.bottomMargin = DensityUtil.dip2px(getContext(),5);
        addView(mFirstLineDiceView,layoutParams);
        addView(mSecondLineDiceView,layoutParams);
        addView(mThreeLineDiceView,layoutParams);

        mFirstLineDiceView.setVisibility(View.INVISIBLE);
        mSecondLineDiceView.setVisibility(View.INVISIBLE);
        mThreeLineDiceView.setVisibility(View.INVISIBLE);
        mFirstAnimatorSet = new AnimatorSet();
        mSecondAnimatorSet = new AnimatorSet();
        mThreeAnimatorSet = new AnimatorSet();
    }

上面代码主要作用是,通过布局获取三个View,然后把View添加到DiceUserAnimLayout里面。然后初始化,这里三个View初始化为INVISIBLE的原因是:如果初始化为GONE,GONE是不会去绘制View的,所以会导致后面获取不到具体位置。最后初始化三个AnimatorSet和通过ArrayList实现的三个队列

接下来我们再设置动画

public void showAnimator(ResultMsgBody resultMsgBody){
        if(mThreeAnimList.size()<=mSecondAnimList.size()&&mThreeAnimList.size()<=mFirstAnimList.size()){
            mThreeAnimList.add(resultMsgBody);
            startThreeAnimator();
        }else if(mSecondAnimList.size()<=mFirstAnimList.size()&&mSecondAnimList.size()<=mThreeAnimList.size()){
            mSecondAnimList.add(resultMsgBody);
            startSecondAnimator();
        }else{
            mFirstAnimList.add(resultMsgBody);
            startFirstAnimator();
        }
    }
    private void startThreeAnimator(){
        if(!threeIsShow){
            if(mThreeAnimList.isEmpty())
                return;
            threeIsShow = true ;
            setViewAnim(mThreeAnimList,mThreeAnimatorSet,mThreeLineDiceView, new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    if(!mThreeAnimList.isEmpty()){
                        animation.removeAllListeners();
                        mThreeAnimList.remove(mThreeAnimList.get(0));
                        threeIsShow = false ;
                        startThreeAnimator();
                    }
                }
            });
        }
    }
    private void startSecondAnimator(){
        if(!secondIsShow){
            if(mSecondAnimList.isEmpty())
                return;
            secondIsShow = true ;
            setViewAnim(mSecondAnimList,mSecondAnimatorSet,mSecondLineDiceView, new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    if(!mSecondAnimList.isEmpty()){
                        animation.removeAllListeners();
                        mSecondAnimList.remove(mSecondAnimList.get(0));
                        secondIsShow = false ;
                        startSecondAnimator();
                    }
                }
            });
        }
    }
    private void startFirstAnimator(){
        if(!firstIsShow){
            if(mFirstAnimList.isEmpty())
                return;
            firstIsShow = true ;
            setViewAnim(mFirstAnimList, mFirstAnimatorSet, mFirstLineDiceView, new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    if(!mFirstAnimList.isEmpty()){
                        animation.removeAllListeners();
                        mFirstAnimList.remove(mFirstAnimList.get(0));
                        firstIsShow = false ;
                        startFirstAnimator();
                    }
                }
            });
        }
    }
    private void setViewAnim(final List<ResultMsgBody> mAnimList,final AnimatorSet animatorSet,
                             final View animView,Animator.AnimatorListener listener){
        if(getContext() instanceof CameraActivity){
            if(mAnimList.get(0).getSound()==1)
                soundPoolHelper.startPlay();
            if(mAnimList.get(0).getVibrate()==1)
                vibrator.vibrate(1000);
        }
        final DiceLayout diceLayout = (DiceLayout) animView.findViewById(R.id.id_user_dice_dl);
        ImageView mDiceUserHead = (ImageView) animView.findViewById(R.id.id_dice_user_head_icon_iv);
        TextView mDiceUserNickNameTv = (TextView) animView.findViewById(R.id.id_play_gift_name_tv);
        mDiceUserNickNameTv.setText(mAnimList.get(0).getSendUserInfo().getNickname());
        String nickNameColor = mAnimList.get(0).getSendUserInfo().getNicknameColor();
        if(!TextUtils.isEmpty(nickNameColor))
            mDiceUserNickNameTv.setTextColor(Color.parseColor(nickNameColor));
        GlideUtils.loadCircleImageView(mDiceUserHead,BitmapUtil.cropWAndHImg(mAnimList.get(0).getSendUserInfo().getAvatar(),
                DensityUtil.dip2px(ForumsApplication.getInstance(),35),
                DensityUtil.dip2px(ForumsApplication.getInstance(),35)),
                R.drawable.head,R.drawable.head);
        ValueAnimator mTransAnimator = ObjectAnimator.ofFloat(animView,"translationX",
                animView.getRight(),animView.getRight()-animView.getWidth());
        mTransAnimator.cancel();
        mTransAnimator.setDuration(2000);
        mTransAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                animView.setAlpha(1.0f);
                animView.setVisibility(View.VISIBLE);
                diceLayout.startRotationAnim(((DiceUserContent)mAnimList.get(0).getMsgBody()).getRockNumberResults(),2);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                animation.removeAllListeners();
            }
        });
        ValueAnimator alphaAnimator = ObjectAnimator.ofFloat(animView,"alpha",
                1.0f,0.0f);
        alphaAnimator.setDuration(500);
        alphaAnimator.setStartDelay(4000);
        alphaAnimator.addListener(listener);
        animatorSet.playSequentially(mTransAnimator,alphaAnimator);
        animatorSet.start();
    }

在外部我们只需要把数据设置进来就行,然后来判断三个队列哪个队列最少数据,把设置进来的数据添加到最少数据的队列里面,然后通过动画逐个展示队列里面的数据。展示完之后我们会在onAnimationEnd把addListener数据清理掉,否则onAnimationEnd会执行很多遍,从而会导致队列显示不正确的BUG,或者引起其他bug,为什么会执行多遍呢,查看下Animator源码就知道了。

public void addListener(AnimatorListener listener) {
        if (mListeners == null) {
            mListeners = new ArrayList<AnimatorListener>();
        }
        mListeners.add(listener);
    }

它是通过ArrayList保存起来了,所以每次addListener都会通过ArrayList保存。

View布局准备好后,接下来就在MainActivity里面来使用下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.common.animdemo.view.DiceAnimLayout
        android:id="@+id/id_dice_anim_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <com.common.animdemo.view.DiceUserAnimLayout
        android:id="@+id/id_user_anim_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="30dp"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击开始摇色子动画"
            android:onClick="startRockDiceClick"
            />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击出现用户消息动画"
            android:onClick="startUserDiceClick"/>
    </LinearLayout>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
    private DiceAnimLayout mDiceAnimLayout;
    private DiceUserAnimLayout mDiceUserAnimLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDiceAnimLayout = (DiceAnimLayout)findViewById(R.id.id_dice_anim_layout);
        mDiceUserAnimLayout = (DiceUserAnimLayout)findViewById(R.id.id_user_anim_layout);
    }
    public void startRockDiceClick(View view){
        int[] rockNumArr = new int[3];
        Random random = new Random();
        rockNumArr[0] = random.nextInt(6)+1;
        rockNumArr[1] = random.nextInt(6)+1;
        rockNumArr[2] = random.nextInt(6)+1;
        mDiceAnimLayout.startAnimation(rockNumArr);
    }
    public void startUserDiceClick(View view){
        int[] rockNumArr = new int[3];
        Random random = new Random();
        rockNumArr[0] = random.nextInt(6)+1;
        rockNumArr[1] = random.nextInt(6)+1;
        rockNumArr[2] = random.nextInt(6)+1;
        DicePo dicePo = new DicePo();
        dicePo.setUserName("用户昵称");
        dicePo.setRocketDiceNum(rockNumArr);
        mDiceUserAnimLayout.showAnimator(dicePo);
    }
}

通过调用startAnimation和showAnimator方法,然后设置每次的旋转点数和其他数据就可以了。最后来看下动效。我这里连击12下看三行队列的效果

这里写图片描述

具体感兴趣的可以下载代码查看

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值