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

来源:互联网 发布:支持spi的读卡器淘宝 编辑:程序博客网 时间:2024/05/18 09:38

转载请标明出处:
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下看三行队列的效果

这里写图片描述

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

1 0